Diff
Not logged in

Differences From:

File src/wikiformat.c part of check-in [df646a7f4c] - Fix some (certainly not all) problems with wiki editing. by drh on 2007-10-12 23:18:35. [view]

To:

File src/wikiformat.c part of check-in [c963a7763d] - Much improved wiki rendering. Automatic paragraph tags now match correctly. All tags should balance. by drh on 2007-10-13 01:18:52. [view]

@@ -32,38 +32,40 @@
 ** 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;
@@ -83,8 +85,9 @@
   { "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,          },
@@ -180,9 +183,8 @@
 */
 #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> */
@@ -189,8 +191,11 @@
 #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 */
@@ -198,9 +203,10 @@
   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  },
@@ -315,8 +321,10 @@
   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 */
@@ -439,9 +447,9 @@
 ** 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;
@@ -742,15 +750,26 @@
   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 [...]
@@ -814,11 +833,12 @@
         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);
@@ -833,8 +853,10 @@
           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;
       }
@@ -846,8 +868,10 @@
           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;
       }
@@ -854,12 +878,14 @@
       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, "&lt;", 4);
         }else if( z[0]=='&' ){
           blob_append(p->pOut, "&amp;", 5);
@@ -870,9 +896,9 @@
         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];
@@ -897,9 +923,9 @@
         blob_append(p->pOut, "</a>", 4);
         break;
       }
       case TOKEN_TEXT: {
-        addMissingMarkup(p);
+        startAutoParagraph(p);
         blob_append(p->pOut, z, n);
         break;
       }
       case TOKEN_MARKUP: {
@@ -914,8 +940,10 @@
             blob_append(p->pOut, "&lt;", 4);
             n = 1;
           }
         }else if( markup.iCode==MARKUP_INVALID ){
+          unparseMarkup(&markup);
+          startAutoParagraph(p);
           blob_append(p->pOut, "&lt;", 4);
           n = 1;
         }else if( (markup.iType&MUTYPE_FONT)==0
                     && (p->state & FONT_MARKUP_ONLY)!=0 ){
@@ -937,8 +965,9 @@
           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);
@@ -958,9 +987,19 @@
             }
             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);
@@ -969,8 +1008,9 @@
       }
     }
     z += n;
   }
+  endAutoParagraph(p);
 }
 
 
 /*
@@ -979,14 +1019,15 @@
 ** 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();
@@ -1008,7 +1049,7 @@
   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, "-");
 }