Index: src/wikiformat.c ================================================================== --- src/wikiformat.c +++ src/wikiformat.c @@ -7,11 +7,11 @@ ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ** General Public License for more details. -** +** ** You should have received a copy of the GNU General Public ** License along with this library; if not, write to the ** Free Software Foundation, Inc., 59 Temple Place - Suite 330, ** Boston, MA 02111-1307, USA. ** @@ -150,11 +150,11 @@ /* ** Allowed markup. ** ** Except for MARKUP_INVALID, this must all be in alphabetical order ** and in numerical sequence. The first markup type must be zero. -** The value for MARKUP_XYZ must correspond to the <xyz> entry +** The value for MARKUP_XYZ must correspond to the <xyz> entry ** in aAllowedMarkup[]. */ #define MARKUP_INVALID 0 #define MARKUP_A 1 #define MARKUP_ADDRESS 2 @@ -189,23 +189,24 @@ #define MARKUP_P 31 #define MARKUP_PRE 32 #define MARKUP_S 33 #define MARKUP_SAMP 34 #define MARKUP_SMALL 35 -#define MARKUP_STRIKE 36 -#define MARKUP_STRONG 37 -#define MARKUP_SUB 38 -#define MARKUP_SUP 39 -#define MARKUP_TABLE 40 -#define MARKUP_TD 41 -#define MARKUP_TH 42 -#define MARKUP_TR 43 -#define MARKUP_TT 44 -#define MARKUP_U 45 -#define MARKUP_UL 46 -#define MARKUP_VAR 47 -#define MARKUP_VERBATIM 48 +#define MARKUP_SPAN 36 +#define MARKUP_STRIKE 37 +#define MARKUP_STRONG 38 +#define MARKUP_SUB 39 +#define MARKUP_SUP 40 +#define MARKUP_TABLE 41 +#define MARKUP_TD 42 +#define MARKUP_TH 43 +#define MARKUP_TR 44 +#define MARKUP_TT 45 +#define MARKUP_U 46 +#define MARKUP_UL 47 +#define MARKUP_VAR 48 +#define MARKUP_VERBATIM 49 /* ** The various markup is divided into the following types: */ #define MUTYPE_SINGLE 0x0001 /* <img>, <br>, or <hr> */ @@ -258,46 +259,47 @@ { "h2", MARKUP_H2, MUTYPE_BLOCK, AMSK_ALIGN }, { "h3", MARKUP_H3, MUTYPE_BLOCK, AMSK_ALIGN }, { "h4", MARKUP_H4, MUTYPE_BLOCK, AMSK_ALIGN }, { "h5", MARKUP_H5, MUTYPE_BLOCK, AMSK_ALIGN }, { "h6", MARKUP_H6, MUTYPE_BLOCK, AMSK_ALIGN }, - { "hr", MARKUP_HR, MUTYPE_SINGLE, + { "hr", MARKUP_HR, MUTYPE_SINGLE, AMSK_ALIGN|AMSK_COLOR|AMSK_SIZE|AMSK_WIDTH }, { "i", MARKUP_I, MUTYPE_FONT, 0 }, - { "img", MARKUP_IMG, MUTYPE_SINGLE, + { "img", MARKUP_IMG, MUTYPE_SINGLE, AMSK_ALIGN|AMSK_ALT|AMSK_BORDER|AMSK_HEIGHT| AMSK_HSPACE|AMSK_SRC|AMSK_VSPACE|AMSK_WIDTH }, { "kbd", MARKUP_KBD, MUTYPE_FONT, 0 }, - { "li", MARKUP_LI, MUTYPE_LI, + { "li", MARKUP_LI, MUTYPE_LI, AMSK_TYPE|AMSK_VALUE }, { "nobr", MARKUP_NOBR, MUTYPE_FONT, 0 }, { "nowiki", MARKUP_NOWIKI, MUTYPE_SPECIAL, 0 }, - { "ol", MARKUP_OL, MUTYPE_LIST, + { "ol", MARKUP_OL, MUTYPE_LIST, AMSK_START|AMSK_TYPE|AMSK_COMPACT }, { "p", MARKUP_P, MUTYPE_BLOCK, AMSK_ALIGN }, { "pre", MARKUP_PRE, MUTYPE_BLOCK, 0 }, { "s", MARKUP_S, MUTYPE_FONT, 0 }, { "samp", MARKUP_SAMP, MUTYPE_FONT, 0 }, { "small", MARKUP_SMALL, MUTYPE_FONT, 0 }, + { "span", MARKUP_SPAN, MUTYPE_FONT, 0 }, { "strike", MARKUP_STRIKE, MUTYPE_FONT, 0 }, { "strong", MARKUP_STRONG, MUTYPE_FONT, 0 }, { "sub", MARKUP_SUB, MUTYPE_FONT, 0 }, { "sup", MARKUP_SUP, MUTYPE_FONT, 0 }, - { "table", MARKUP_TABLE, MUTYPE_TABLE, + { "table", MARKUP_TABLE, MUTYPE_TABLE, AMSK_ALIGN|AMSK_BGCOLOR|AMSK_BORDER|AMSK_CELLPADDING| AMSK_CELLSPACING|AMSK_HSPACE|AMSK_VSPACE }, - { "td", MARKUP_TD, MUTYPE_TD, + { "td", MARKUP_TD, MUTYPE_TD, AMSK_ALIGN|AMSK_BGCOLOR|AMSK_COLSPAN| AMSK_ROWSPAN|AMSK_VALIGN }, { "th", MARKUP_TH, MUTYPE_TD, AMSK_ALIGN|AMSK_BGCOLOR|AMSK_COLSPAN| AMSK_ROWSPAN|AMSK_VALIGN }, - { "tr", MARKUP_TR, MUTYPE_TR, + { "tr", MARKUP_TR, MUTYPE_TR, AMSK_ALIGN|AMSK_BGCOLOR||AMSK_VALIGN }, { "tt", MARKUP_TT, MUTYPE_FONT, 0 }, { "u", MARKUP_U, MUTYPE_FONT, 0 }, - { "ul", MARKUP_UL, MUTYPE_LIST, + { "ul", MARKUP_UL, MUTYPE_LIST, AMSK_TYPE|AMSK_COMPACT }, { "var", MARKUP_VAR, MUTYPE_FONT, 0 }, { "verbatim", MARKUP_VERBATIM, MUTYPE_SPECIAL, AMSK_ID }, }; @@ -332,11 +334,12 @@ #define TOKEN_PARAGRAPH 4 /* blank lines */ #define TOKEN_NEWLINE 5 /* A single "\n" */ #define TOKEN_BULLET 6 /* " * " */ #define TOKEN_ENUM 7 /* " \(?\d+[.)]? " */ #define TOKEN_INDENT 8 /* " " */ -#define TOKEN_TEXT 9 /* None of the above */ +#define TOKEN_COMMENT 9 /* <!-- --> */ +#define TOKEN_TEXT 10 /* None of the above */ /* ** State flags */ #define AT_NEWLINE 0x001 /* At start of a line */ @@ -376,10 +379,28 @@ ** it is not well-formed markup, return 0. */ static int markupLength(const char *z){ int n = 1; int inparen = 0; + + // is a comment - if valid return n else return 0 + if( z[n]=='!' ){ + n++; + if (z[n]!='-') return 0; + n++; + if (z[n]!='-') return 0; + n++; + while (z[n]){ + while (z[n] && z[n]!='>') n++; + if (!z[n]) return 0; + n++; + if(n>3 && z[n-3]=='-' && z[n-2]=='-') + return (n>7) ? n : 0; + } + return 0; + } + if( z[n]=='/' ){ n++; } if( !isalpha(z[n]) ) return 0; while( isalnum(z[n]) ){ n++; } if( z[n]!='>' && !isspace(z[n]) ) return 0; while( z[n] && (z[n]!='>' || inparen) ){ @@ -433,11 +454,11 @@ while( (c = z[0])!=0 && c!='<' && c!='&' && (useWiki==0 || (c!='[' && c!='\n')) ){ n++; z++; } - return n; + return n; } /* ** Return true if z[] begins with an HTML character element. */ @@ -554,13 +575,19 @@ */ static int nextToken(const char *z, Renderer *p, int *pTokenType){ int n; if( z[0]=='<' ){ n = markupLength(z); - if( n>0 ){ - *pTokenType = TOKEN_MARKUP; - return n; + + if( n>1 ){ + if (z[1]=='!'){ + *pTokenType = TOKEN_COMMENT; + return n; + } else { + *pTokenType = TOKEN_MARKUP; + return n; + } }else{ *pTokenType = TOKEN_CHARACTER; return 1; } } @@ -626,11 +653,11 @@ /* ** z[] is an HTML markup element - something that begins with '<'. ** Parse this element into the p structure. ** -** The content of z[] might be modified by converting characters +** The content of z[] might be modified by converting characters ** to lowercase and by inserting some "\000" characters. */ static void parseMarkup(ParsedMarkup *p, char *z){ int i, j, c; int iACode; @@ -644,11 +671,11 @@ }else{ p->endTag = 0; i = 1; } j = 0; - while( isalnum(z[i]) ){ + while( isalnum(z[i]) ){ if( j<sizeof(zTag)-1 ) zTag[j++] = tolower(z[i]); i++; } zTag[j] = 0; p->iCode = findTag(zTag); @@ -656,11 +683,11 @@ p->nAttr = 0; while( isspace(z[i]) ){ i++; } while( p->nAttr<8 && isalpha(z[i]) ){ int attrOk; /* True to preserver attribute. False to ignore it */ j = 0; - while( isalnum(z[i]) ){ + while( isalnum(z[i]) ){ if( j<sizeof(zTag)-1 ) zTag[j++] = tolower(z[i]); i++; } zTag[j] = 0; p->aAttr[p->nAttr].iACode = iACode = findAttr(zTag); @@ -799,11 +826,11 @@ } } /* ** Attempt to find a find a tag of type iTag with id zId. Return -1 -** if not found. If found, return its stack level. +** if not found. If found, return its stack level. */ static int findTagWithId(Renderer *p, int iTag, const char *zId){ int i; assert( zId!=0 ); for(i=p->nStack-1; i>=0; i--){ @@ -889,11 +916,11 @@ canonical16(zLower, n+1); memcpy(zUpper, zLower, n+1); zUpper[n-1]++; if( once ){ const char *zClosedExpr = db_get("ticket-closed-expr", "status='Closed'"); - db_static_prepare(&q, + db_static_prepare(&q, "SELECT %s FROM ticket " " WHERE tkt_uuid>=:lwr AND tkt_uuid<:upr", zClosedExpr ); once = 0; @@ -927,13 +954,13 @@ int nClose /* Bytes available in zClose[] */ ){ const char *zTerm = "</a>"; assert( nClose>10 ); - if( strncmp(zTarget, "http:", 5)==0 + if( strncmp(zTarget, "http:", 5)==0 || strncmp(zTarget, "https:", 6)==0 - || strncmp(zTarget, "ftp:", 4)==0 + || strncmp(zTarget, "ftp:", 4)==0 || strncmp(zTarget, "mailto:", 7)==0 ){ blob_appendf(p->pOut, "<a href=\"%s\">", zTarget); }else if( zTarget[0]=='/' ){ if( 1 /* g.okHistory */ ){ @@ -1022,10 +1049,19 @@ while( z[0] ){ n = nextToken(z, p, &tokenType); p->state &= ~(AT_NEWLINE|AT_PARAGRAPH); switch( tokenType ){ + + case TOKEN_COMMENT: { + if (p->inVerbatim){ + blob_append(p->pOut, htmlize(z, n), -1); + } else { + blob_append(p->pOut, z, n); + } + break; + } case TOKEN_PARAGRAPH: { if( inlineOnly ){ /* blob_append(p->pOut, " ¶ ", -1); */ blob_append(p->pOut, " ", -1); }else{ @@ -1143,11 +1179,11 @@ int iDiv; parseMarkup(&markup, z); /* Markup of the form </div id=ID> where there is a matching ** ID somewhere on the stack. Exit the verbatim if were are in - ** it. Pop the stack up to the matching <div>. Discard the + ** it. Pop the stack up to the matching <div>. Discard the ** </div> */ if( markup.iCode==MARKUP_DIV && markup.endTag && (zId = markupId(&markup))!=0 && (iDiv = findTagWithId(p, MARKUP_DIV, zId))>=0 @@ -1167,11 +1203,11 @@ p->nStack--; }else /* If within <verbatim id=ID> ignore everything other than ** </verbatim id=ID> and the </dev id=ID2> above. - */ + */ if( p->inVerbatim ){ if( endVerbatim(p, &markup) ){ p->inVerbatim = 0; p->state = p->preVerbState; blob_append(p->pOut, "</pre>", 6); @@ -1225,11 +1261,11 @@ (p->state & ALLOW_WIKI)!=0); }else /* Enter <verbatim> processing. With verbatim enabled, all other ** markup other than the corresponding end-tag with the same ID is - ** ignored. + ** ignored. */ if( markup.iCode==MARKUP_VERBATIM ){ if( markup.nAttr==1 ){ p->zVerbatimId = markup.aAttr[0].zValue; }else{ @@ -1298,11 +1334,11 @@ ** reply. */ 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; if( flags & WIKI_NOBLOCK ){ renderer.state |= INLINE_MARKUP_ONLY; }