Overview
SHA1 Hash: | c963a7763d96836b4f407a837718c14bf391ec08 |
---|---|
Date: | 2007-10-13 01:18:52 |
User: | drh |
Comment: | Much improved wiki rendering. Automatic paragraph tags now match correctly. All tags should balance. |
Timelines: | ancestors | descendants | both | trunk |
Other Links: | files | ZIP archive | manifest |
Tags And Properties
- branch=trunk inherited from [a28c83647d]
- sym-trunk inherited from [a28c83647d]
Changes
[hide diffs]Modified src/timeline.c from [ca926d4172] to [4abc5a4987].
@@ -161,11 +161,11 @@ } }else{ hyperlink_to_uuid(zUuid); } db_column_blob(pQuery, 3, &comment); - wiki_convert(&comment, 0); + wiki_convert(&comment, 0, WIKI_INLINE); blob_reset(&comment); @ (by %h(zUser))</td></tr> } @ </table> }
Modified src/wiki.c from [ba2a75dd4c] to [15b33bf930].
@@ -146,11 +146,11 @@ mprintf("%s/whistory?name=%T", g.zTop, zPageName)); } zHtmlPageName = mprintf("%h", zPageName); style_header(zHtmlPageName); blob_init(&wiki, zBody, -1); - wiki_convert(&wiki, 0); + wiki_convert(&wiki, 0, 0); blob_reset(&wiki); manifest_clear(&m); style_footer(); } @@ -238,11 +238,11 @@ style_header(zHtmlPageName); if( P("preview")!=0 ){ blob_zero(&wiki); blob_append(&wiki, zBody, -1); @ Preview:<hr> - wiki_convert(&wiki, 0); + wiki_convert(&wiki, 0, 0); @ <hr> blob_reset(&wiki); } for(n=2, z=zBody; z[0]; z++){ if( z[0]=='\n' ) n++; @@ -363,11 +363,11 @@ if( P("preview")!=0 ){ Blob preview; blob_zero(&preview); appendRemark(&preview); @ Preview:<hr> - wiki_convert(&preview, 0); + wiki_convert(&preview, 0, 0); @ <hr> blob_reset(&preview); } zUser = PD("u", g.zLogin); @ <form method="POST" action="%s(g.zBaseURL)/wikiappend">
Modified src/wikiformat.c from [13dfb968ea] to [a1f06c841d].
@@ -31,40 +31,42 @@ /* ** Allowed wiki transformation operations */ #define WIKI_NOFOLLOW 0x001 #define WIKI_HTML 0x002 +#define WIKI_INLINE 0x004 /* Do not surround with <p>..</p> */ #endif /* ** These are the only markup attributes allowed. */ -#define ATTR_ALIGN 0x000001 -#define ATTR_ALT 0x000002 -#define ATTR_BGCOLOR 0x000004 -#define ATTR_BORDER 0x000008 -#define ATTR_CELLPADDING 0x000010 -#define ATTR_CELLSPACING 0x000020 -#define ATTR_CLEAR 0x000040 -#define ATTR_COLOR 0x000080 -#define ATTR_COLSPAN 0x000100 -#define ATTR_COMPACT 0x000200 -#define ATTR_FACE 0x000400 -#define ATTR_HEIGHT 0x000800 -#define ATTR_HREF 0x001000 -#define ATTR_HSPACE 0x002000 -#define ATTR_ID 0x004000 -#define ATTR_ROWSPAN 0x008000 -#define ATTR_SIZE 0x010000 -#define ATTR_SRC 0x020000 -#define ATTR_START 0x040000 -#define ATTR_TYPE 0x080000 -#define ATTR_VALIGN 0x100000 -#define ATTR_VALUE 0x200000 -#define ATTR_VSPACE 0x400000 -#define ATTR_WIDTH 0x800000 +#define ATTR_ALIGN 0x0000001 +#define ATTR_ALT 0x0000002 +#define ATTR_BGCOLOR 0x0000004 +#define ATTR_BORDER 0x0000008 +#define ATTR_CELLPADDING 0x0000010 +#define ATTR_CELLSPACING 0x0000020 +#define ATTR_CLEAR 0x0000040 +#define ATTR_COLOR 0x0000080 +#define ATTR_COLSPAN 0x0000100 +#define ATTR_COMPACT 0x0000200 +#define ATTR_FACE 0x0000400 +#define ATTR_HEIGHT 0x0000800 +#define ATTR_HREF 0x0001000 +#define ATTR_HSPACE 0x0002000 +#define ATTR_ID 0x0004000 +#define ATTR_NAME 0x0008000 +#define ATTR_ROWSPAN 0x0010000 +#define ATTR_SIZE 0x0020000 +#define ATTR_SRC 0x0040000 +#define ATTR_START 0x0080000 +#define ATTR_TYPE 0x0100000 +#define ATTR_VALIGN 0x0200000 +#define ATTR_VALUE 0x0400000 +#define ATTR_VSPACE 0x0800000 +#define ATTR_WIDTH 0x1000000 static const struct AllowedAttribute { const char *zName; unsigned int iMask; } aAttribute[] = { @@ -82,10 +84,11 @@ { "face", ATTR_FACE, }, { "height", ATTR_HEIGHT, }, { "href", ATTR_HREF, }, { "hspace", ATTR_HSPACE, }, { "id", ATTR_ID, }, + { "name", ATTR_NAME, }, { "rowspan", ATTR_ROWSPAN, }, { "size", ATTR_SIZE, }, { "src", ATTR_SRC, }, { "start", ATTR_START, }, { "type", ATTR_TYPE, }, @@ -179,29 +182,32 @@ ** The various markup is divided into the following types: */ #define MUTYPE_SINGLE 0x0001 /* <img>, <br>, or <hr> */ #define MUTYPE_BLOCK 0x0002 /* Forms a new paragraph. ex: <p>, <h2> */ #define MUTYPE_FONT 0x0004 /* Font changes. ex: <b>, <font>, <sub> */ -#define MUTYPE_LINK 0x0008 /* Hyperlink: <a> */ #define MUTYPE_LIST 0x0010 /* Lists. <ol>, <ul>, or <dl> */ #define MUTYPE_LI 0x0020 /* List items. <li>, <dd>, <dt> */ #define MUTYPE_TABLE 0x0040 /* <table> */ #define MUTYPE_TR 0x0080 /* <tr> */ #define MUTYPE_TD 0x0100 /* <td> or <th> */ #define MUTYPE_SPECIAL 0x0200 /* <nowiki> or <verbatim> */ #define MUTYPE_HYPERLINK 0x0400 /* <a> */ +/* +** These markup types must have an end tag. +*/ #define MUTYPE_STACK (MUTYPE_BLOCK | MUTYPE_FONT | MUTYPE_LIST | MUTYPE_TABLE) static const struct AllowedMarkup { const char *zName; /* Name of the markup */ char iCode; /* The MARKUP_* code */ short int iType; /* The MUTYPE_* code */ int allowedAttr; /* Allowed attributes on this markup */ } aMarkup[] = { { 0, MARKUP_INVALID, 0, 0 }, - { "a", MARKUP_A, MUTYPE_HYPERLINK, ATTR_HREF }, + { "a", MARKUP_A, MUTYPE_HYPERLINK, + ATTR_HREF|ATTR_NAME }, { "address", MARKUP_ADDRESS, MUTYPE_BLOCK, 0 }, { "b", MARKUP_B, MUTYPE_FONT, 0 }, { "big", MARKUP_BIG, MUTYPE_FONT, 0 }, { "blockquote", MARKUP_BLOCKQUOTE, MUTYPE_BLOCK, 0 }, { "br", MARKUP_BR, MUTYPE_SINGLE, ATTR_CLEAR }, @@ -314,10 +320,12 @@ Blob *pOut; /* Output appended to this blob */ int state; /* Flag that govern rendering */ int wikiList; /* Current wiki list type */ int inVerbatim; /* True in <verbatim> mode */ int preVerbState; /* Value of state prior to verbatim */ + int wantAutoParagraph; /* True if a <p> is desired */ + int inAutoParagraph; /* True if within an automatic paragraph */ const char *zVerbatimId; /* The id= attribute of <verbatim> */ int nStack; /* Number of elements on the stack */ int nAlloc; /* Space allocated for aStack */ unsigned char *aStack; /* Open markup stack */ }; @@ -438,11 +446,11 @@ ** ** Syntax: ** * a tab or two or more spaces ** * one or more digits ** * optional "." -** * another tab or two or more additional spaces +** * another tab or two ore more spaces. ** */ static int enumLength(const char *z){ int i, n; n = 0; @@ -741,17 +749,28 @@ } return p->aStack[i-1]; } /* -** Add missing markup in preparation for writing text. -** -** "Missing" markup are things like start tags for table rows -** or table columns or paragraphs that are omitted from input. +** Begin a new paragraph if that something that is needed. +*/ +static void startAutoParagraph(Renderer *p){ + if( p->wantAutoParagraph==0 ) return; + blob_appendf(p->pOut, "<p>", -1); + pushStack(p, MARKUP_P); + p->wantAutoParagraph = 0; + p->inAutoParagraph = 1; +} + +/* +** End a paragraph if we are in one. */ -static void addMissingMarkup(Renderer *p){ - /* TBD */ +static void endAutoParagraph(Renderer *p){ + if( p->inAutoParagraph ){ + popStackToTag(p, MARKUP_P); + p->inAutoParagraph = 0; + } } /* ** Resolve a hyperlink. The argument is the content of the [...] ** in the wiki. Append the URL to the output of the Renderer. @@ -813,13 +832,14 @@ case TOKEN_PARAGRAPH: { if( p->wikiList ){ popStackToTag(p, p->wikiList); p->wikiList = 0; } - blob_append(p->pOut, "\n\n<p>", -1); - p->state |= AT_PARAGRAPH|AT_NEWLINE; - popStackToTag(p, MARKUP_P); + endAutoParagraph(p); + blob_appendf(p->pOut, "\n\n", 1); + p->wantAutoParagraph = 1; + p->state |= AT_PARAGRAPH|AT_NEWLINE; break; } case TOKEN_NEWLINE: { blob_append(p->pOut, "\n", 1); p->state |= AT_NEWLINE; @@ -832,10 +852,12 @@ } pushStack(p, MARKUP_UL); blob_append(p->pOut, "<ul>", 4); p->wikiList = MARKUP_UL; } + popStackToTag(p, MARKUP_LI); + startAutoParagraph(p); pushStack(p, MARKUP_LI); blob_append(p->pOut, "<li>", 4); break; } case TOKEN_ENUM: { @@ -845,22 +867,26 @@ } pushStack(p, MARKUP_OL); blob_append(p->pOut, "<ol>", 4); p->wikiList = MARKUP_OL; } + popStackToTag(p, MARKUP_LI); + startAutoParagraph(p); pushStack(p, MARKUP_LI); blob_appendf(p->pOut, "<li value=\"%d\">", atoi(z)); break; } case TOKEN_INDENT: { assert( p->wikiList==0 ); pushStack(p, MARKUP_BLOCKQUOTE); blob_append(p->pOut, "<blockquote>", -1); + p->wantAutoParagraph = 0; p->wikiList = MARKUP_BLOCKQUOTE; break; } case TOKEN_CHARACTER: { + startAutoParagraph(p); if( z[0]=='<' ){ blob_append(p->pOut, "<", 4); }else if( z[0]=='&' ){ blob_append(p->pOut, "&", 5); } @@ -869,11 +895,11 @@ case TOKEN_LINK: { char *zTarget; char *zDisplay = 0; int i, j; int savedState; - addMissingMarkup(p); + startAutoParagraph(p); zTarget = &z[1]; for(i=1; z[i] && z[i]!=']'; i++){ if( z[i]=='|' && zDisplay==0 ){ zDisplay = &z[i+1]; z[i] = 0; @@ -896,11 +922,11 @@ p->state = savedState; blob_append(p->pOut, "</a>", 4); break; } case TOKEN_TEXT: { - addMissingMarkup(p); + startAutoParagraph(p); blob_append(p->pOut, z, n); break; } case TOKEN_MARKUP: { parseMarkup(&markup, z); @@ -913,10 +939,12 @@ unparseMarkup(&markup); blob_append(p->pOut, "<", 4); n = 1; } }else if( markup.iCode==MARKUP_INVALID ){ + unparseMarkup(&markup); + startAutoParagraph(p); blob_append(p->pOut, "<", 4); n = 1; }else if( (markup.iType&MUTYPE_FONT)==0 && (p->state & FONT_MARKUP_ONLY)!=0 ){ /* Do nothing */ @@ -936,10 +964,11 @@ } p->inVerbatim = 1; p->preVerbState = p->state; p->state &= ~ALLOW_WIKI; blob_append(p->pOut, "<pre>", 5); + p->wantAutoParagraph = 0; }else if( markup.iType==MUTYPE_LI ){ if( backupToType(p, MUTYPE_LIST)==0 ){ pushStack(p, MARKUP_UL); blob_append(p->pOut, "<ul>", 4); } @@ -957,11 +986,21 @@ blob_append(p->pOut, "<tr>", 4); } pushStack(p, markup.iCode); renderMarkup(p->pOut, &markup); } + }else if( markup.iType==MUTYPE_HYPERLINK ){ + popStackToTag(p, markup.iCode); + startAutoParagraph(p); + renderMarkup(p->pOut, &markup); + pushStack(p, markup.iCode); }else{ + if( markup.iType==MUTYPE_FONT ){ + startAutoParagraph(p); + }else if( markup.iType==MUTYPE_BLOCK ){ + p->wantAutoParagraph = 0; + } if( (markup.iType & MUTYPE_STACK )!=0 ){ pushStack(p, markup.iCode); } renderMarkup(p->pOut, &markup); } @@ -968,10 +1007,11 @@ break; } } z += n; } + endAutoParagraph(p); } /* ** Transform the text in the pIn blob. Write the results @@ -978,16 +1018,17 @@ ** into the pOut blob. The pOut blob should already be ** initialized. The output is merely appended to pOut. ** If pOut is NULL, then the output is appended to the CGI ** reply. */ -void wiki_convert(Blob *pIn, Blob *pOut){ +void wiki_convert(Blob *pIn, Blob *pOut, int flags){ char *z; Renderer renderer; memset(&renderer, 0, sizeof(renderer)); renderer.state = ALLOW_WIKI|AT_NEWLINE|AT_PARAGRAPH; + renderer.wantAutoParagraph = (flags & WIKI_INLINE)==0; if( pOut ){ renderer.pOut = pOut; }else{ renderer.pOut = cgi_output_blob(); } @@ -1007,8 +1048,8 @@ void test_wiki_render(void){ Blob in, out; if( g.argc!=3 ) usage("FILE"); blob_zero(&out); blob_read_from_file(&in, g.argv[2]); - wiki_convert(&in, &out); + wiki_convert(&in, &out, 0); blob_write_to_file(&out, "-"); }