Check-in [ab637af752]
Not logged in
Overview

SHA1 Hash:ab637af752641f503f69e1a12ac6c129a8758b35
Date: 2007-09-28 15:44:08
User: drh
Comment:Add enumeration lists and indented paragraphs in the wiki.
Timelines: ancestors | descendants | both | trunk
Other Links: files | ZIP archive | manifest

Tags And Properties
Changes
[hide diffs]

Modified ideas.txt from [403e94306f] to [555b72ded1].

@@ -43,22 +43,44 @@
    * Three pages:  creation, display, and edit
    * HTML
    * [[field]] to substitute the appropriate form or display element
 
 ------------------------------------------------------------------------
-Wiki header format:
-   "WikiPage"
-   parent: UUID*
-   title: TEXT
-   pagename: TEXT
-   mode: (readonly|appendonly|readwrite)
-   attachment: UUID name description
-
-   * Header ends with a blank line.  wiki content follows.
-
-Need a dephantomize algorithm
-
+Change to wiki:
+
+   A uuid filename description
+   D datetime
+   P uuid ...
+   U user
+   W wikipagename uuid
+   Z md5sum
+
+On page:
+
+   <title>....</title>
+   <readonly/>
+
+Hyperlinks:
+
+   [lowercasehex]       /info/lowercasehex
+   [attachment.gif]     inline image
+   [tagname]            /info/tagname
+   [wikipagename]       /wiki/wikipagename
+   [/internal/page]     /internal/page
+   [http:...]           external link
+
+Markup:
+
+   blank-line           paragraph break
+   _*__                 bullet
+   __                   indentation
+   _#.__                enumeration
+   *text*               bold
+   _text_               italic
+
+
+------------------------------------------------------------------------
 
 Random thoughts:
 
   * Plink.isprim changed to record:
      +  child is the principal descendent of parent. (1)

Modified src/wiki.c from [804763a66e] to [3d314ebfeb].

@@ -109,11 +109,11 @@
     }
 
     /* Render the page */
     style_header(zTitle);
     blob_init(&page, z, -1);
-    wiki_convert(&page, cgi_output_blob(), WIKI_HTML);
+    wiki_convert(&page, 0);
     blob_reset(&src);
   }else{
     style_header("Unknown Wiki Page");
     @ The wiki page "%h(zPageName)" does not exist.
   }

Modified src/wikiformat.c from [12488f8f7c] to [75615129b5].

@@ -123,58 +123,58 @@
 ** 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
 ** in aAllowedMarkup[].
 */
-#define MARKUP_INVALID         255
-#define MARKUP_A                 0
-#define MARKUP_ADDRESS           1
-#define MARKUP_B                 2
-#define MARKUP_BIG               3
-#define MARKUP_BLOCKQUOTE        4
-#define MARKUP_BR                5
-#define MARKUP_CENTER            6
-#define MARKUP_CITE              7
-#define MARKUP_CODE              8
-#define MARKUP_DD                9
-#define MARKUP_DFN              10
-#define MARKUP_DL               11
-#define MARKUP_DT               12
-#define MARKUP_EM               13
-#define MARKUP_FONT             14
-#define MARKUP_H1               15
-#define MARKUP_H2               16
-#define MARKUP_H3               17
-#define MARKUP_H4               18
-#define MARKUP_H5               19
-#define MARKUP_H6               20
-#define MARKUP_HR               21
-#define MARKUP_IMG              22
-#define MARKUP_I                23
-#define MARKUP_KBD              24
-#define MARKUP_LI               25
-#define MARKUP_NOBR             26
-#define MARKUP_NOWIKI           27
-#define MARKUP_OL               28
-#define MARKUP_P                29
-#define MARKUP_PRE              30
-#define MARKUP_S                31
-#define MARKUP_SAMP             32
-#define MARKUP_SMALL            33
-#define MARKUP_STRIKE           34
-#define MARKUP_STRONG           35
-#define MARKUP_SUB              36
-#define MARKUP_SUP              37
-#define MARKUP_TABLE            38
-#define MARKUP_TD               39
-#define MARKUP_TH               40
-#define MARKUP_TR               41
-#define MARKUP_TT               42
-#define MARKUP_U                43
-#define MARKUP_UL               44
-#define MARKUP_VAR              45
-#define MARKUP_VERBATIM         46
+#define MARKUP_INVALID           0
+#define MARKUP_A                 1
+#define MARKUP_ADDRESS           2
+#define MARKUP_B                 3
+#define MARKUP_BIG               4
+#define MARKUP_BLOCKQUOTE        5
+#define MARKUP_BR                6
+#define MARKUP_CENTER            7
+#define MARKUP_CITE              8
+#define MARKUP_CODE              9
+#define MARKUP_DD               10
+#define MARKUP_DFN              11
+#define MARKUP_DL               12
+#define MARKUP_DT               13
+#define MARKUP_EM               14
+#define MARKUP_FONT             15
+#define MARKUP_H1               16
+#define MARKUP_H2               17
+#define MARKUP_H3               18
+#define MARKUP_H4               19
+#define MARKUP_H5               20
+#define MARKUP_H6               21
+#define MARKUP_HR               22
+#define MARKUP_IMG              23
+#define MARKUP_I                24
+#define MARKUP_KBD              25
+#define MARKUP_LI               26
+#define MARKUP_NOBR             27
+#define MARKUP_NOWIKI           28
+#define MARKUP_OL               29
+#define MARKUP_P                30
+#define MARKUP_PRE              31
+#define MARKUP_S                32
+#define MARKUP_SAMP             33
+#define MARKUP_SMALL            34
+#define MARKUP_STRIKE           35
+#define MARKUP_STRONG           36
+#define MARKUP_SUB              37
+#define MARKUP_SUP              38
+#define MARKUP_TABLE            39
+#define MARKUP_TD               40
+#define MARKUP_TH               41
+#define MARKUP_TR               42
+#define MARKUP_TT               43
+#define MARKUP_U                44
+#define MARKUP_UL               45
+#define MARKUP_VAR              46
+#define MARKUP_VERBATIM         47
 
 /*
 ** The various markup is divided into the following types:
 */
 #define MUTYPE_SINGLE      0x0001   /* <img>, <br>, or <hr> */
@@ -195,10 +195,11 @@
   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 },
  { "address",       MARKUP_ADDRESS,      MUTYPE_BLOCK,         0  },
  { "b",             MARKUP_B,            MUTYPE_FONT,          0  },
  { "big",           MARKUP_BIG,          MUTYPE_FONT,          0  },
  { "blockquote",    MARKUP_BLOCKQUOTE,   MUTYPE_BLOCK,         0  },
@@ -263,11 +264,11 @@
 /*
 ** Use binary search to locate a tag in the aMarkup[] table.
 */
 static int findTag(const char *z){
   int i, c, first, last;
-  first = 0;
+  first = 1;
   last = sizeof(aMarkup)/sizeof(aMarkup[0]) - 1;
   while( first<=last ){
     i = (first+last)/2;
     c = strcmp(aMarkup[i].zName, z);
     if( c==0 ){
@@ -300,11 +301,28 @@
 */
 #define AT_NEWLINE        0x001  /* At start of a line */
 #define AT_PARAGRAPH      0x002  /* At start of a paragraph */
 #define ALLOW_WIKI        0x004  /* Allow wiki markup */
 #define FONT_MARKUP_ONLY  0x008  /* Only allow MUTYPE_FONT markup */
-#define IN_LIST           0x010  /* Within <ul> */
+#define IN_LIST           0x010  /* Within wiki <ul> or <ol> */
+
+/*
+** Current state of the rendering engine
+*/
+typedef struct Renderer Renderer;
+struct Renderer {
+  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 */
+  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 */
+};
+
 
 /*
 ** z points to a "<" character.  Check to see if this is the start of
 ** a valid markup.  If it is, return the total number of characters in
 ** the markup including the initial "<" and the terminating ">".  If
@@ -412,10 +430,46 @@
   if( i<2 || isspace(z[n]) ) return 0;
   return n;
 }
 
 /*
+** Check to see if the z[] string is the beginning of a enumeration value.
+** If it is, return the length of the bullet text.  Otherwise return 0.
+**
+** Syntax:
+**    *  a tab or two or more spaces
+**    *  one or more digits
+**    *  optional "."
+**    *  another tab or two or more additional spaces
+**
+*/
+static int enumLength(const char *z){
+  int i, n;
+  n = 0;
+  i = 0;
+  while( z[n]==' ' || z[n]=='\t' ){
+    if( z[n]=='\t' ) i++;
+    i++;
+    n++;
+  }
+  if( i<2 ) return 0;
+  for(i=0; isdigit(z[n]); i++, n++){}
+  if( i==0 ) return 0;
+  if( z[n]=='.' ){
+    n++;
+  }
+  i = 0;
+  while( z[n]==' ' || z[n]=='\t' ){
+    if( z[n]=='\t' ) i++;
+    i++;
+    n++;
+  }
+  if( i<2 || isspace(z[n]) ) return 0;
+  return n;
+}
+
+/*
 ** Check to see if the z[] string is the beginning of an indented
 ** paragraph.  If it is, return the length of the indent.  Otherwise
 ** return 0.
 */
 static int indentLength(const char *z){
@@ -483,17 +537,15 @@
       n = bulletLength(z);
       if( n>0 ){
         *pTokenType = TOKEN_BULLET;
         return n;
       }
-#if 0
       n = enumLength(z);
       if( n>0 ){
         *pTokenType = TOKEN_ENUM;
         return n;
       }
-#endif
     }
     if( (state & AT_PARAGRAPH)!=0 && isspace(z[0]) ){
       n = indentLength(z);
       if( n>0 ){
         *pTokenType = TOKEN_INDENT;
@@ -629,25 +681,10 @@
     z[n] = p->aAttr[i].cTerm;
   }
 }
 
 /*
-** Current state of the rendering engine
-*/
-typedef struct Renderer Renderer;
-struct Renderer {
-  Blob *pOut;                 /* Output appended to this blob */
-  int state;                  /* Flag that govern rendering */
-  int inVerbatim;             /* True in <verbatim> mode */
-  int preVerbState;           /* Value of state prior to verbatim */
-  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 */
-};
-
-/*
 ** Pop a single element off of the stack.  As the element is popped,
 ** output its end tag.
 */
 static void popStack(Renderer *p){
   if( p->nStack ){
@@ -686,23 +723,24 @@
 }
 
 /*
 ** Pop the stack until the top-most element of the stack
 ** is an element that matches the type in iMask.  Return
-** true on success.  If the stack does not have an element
+** code of the markup element that is on left on top of the stack.
+** If the stack does not have an element
 ** that matches iMask, then leave the stack unchanged and
-** return false.
+** return false (MARKUP_INVALID).
 */
 static int backupToType(Renderer *p, int iMask){
   int i;
   for(i=p->nStack-1; i>=0 && (aMarkup[p->aStack[i]].iType&iMask)==0; i--){}
   if( i<0 ) return 0;
   i++;
   while( p->nStack>i ){
     popStack(p);
   }
-  return 1;
+  return p->aStack[i-1];
 }
 
 /*
 ** Add missing markup in preparation for writing text.
 **
@@ -767,10 +805,14 @@
   while( z[0] ){
     n = nextToken(z, p->state, &tokenType);
     p->state &= ~(AT_NEWLINE|AT_PARAGRAPH);
     switch( tokenType ){
       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);
         break;
       }
@@ -778,16 +820,40 @@
         blob_append(p->pOut, "\n", 1);
         p->state |= AT_NEWLINE;
         break;
       }
       case TOKEN_BULLET: {
-        if( backupToType(p, MUTYPE_LIST)==0 ){
+        if( p->wikiList!=MARKUP_UL ){
+          if( p->wikiList ){
+            popStackToTag(p, p->wikiList);
+          }
           pushStack(p, MARKUP_UL);
           blob_append(p->pOut, "<ul>", 4);
+          p->wikiList = MARKUP_UL;
         }
         pushStack(p, MARKUP_LI);
         blob_append(p->pOut, "<li>", 4);
+        break;
+      }
+      case TOKEN_ENUM: {
+        if( p->wikiList!=MARKUP_OL ){
+          if( p->wikiList ){
+            popStackToTag(p, p->wikiList);
+          }
+          pushStack(p, MARKUP_OL);
+          blob_append(p->pOut, "<ol>", 4);
+          p->wikiList = MARKUP_OL;
+        }
+        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->wikiList = MARKUP_BLOCKQUOTE;
         break;
       }
       case TOKEN_CHARACTER: {
         if( z[0]=='<' ){
           blob_append(p->pOut, "&lt;", 4);
@@ -904,33 +970,24 @@
 
 /*
 ** Transform the text in the pIn blob.  Write the results
 ** into the pOut blob.  The pOut blob should already be
 ** initialized.  The output is merely appended to pOut.
-**
-** The transformations carried out depend on the ops flag:
-**
-** WIKI_NOFOLLOW
-**
-**     * Add the nofollow attribute to external links
-**
-** WIKI_HTML
-**
-**     * Convert wiki into HTML
-**     * Remove <nowiki> and <verbatium>
-**     * Convert & into &amp;
-**     * Unrecognized markup and markup within <verbatim>
-**       is converted into &lt;...&gt;
-**     * Unauthorized attributes on markup are removed
+** If pOut is NULL, then the output is appended to the CGI
+** reply.
 */
-void wiki_convert(Blob *pIn, Blob *pOut, int ops){
+void wiki_convert(Blob *pIn, Blob *pOut){
   char *z;
   Renderer renderer;
 
   memset(&renderer, 0, sizeof(renderer));
   renderer.state = ALLOW_WIKI|AT_NEWLINE|AT_PARAGRAPH;
-  renderer.pOut = pOut;
+  if( pOut ){
+    renderer.pOut = pOut;
+  }else{
+    renderer.pOut = cgi_output_blob();
+  }
 
   z = blob_str(pIn);
   wiki_render(&renderer, z);
   while( renderer.nStack ){
     popStack(&renderer);
@@ -946,8 +1003,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_HTML);
+  wiki_convert(&in, &out);
   blob_write_to_file(&out, "-");
 }