Fossil

Check-in [b99aa66d]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:add wiki-contents macro to creole parser, plus minor bug fix
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | creole
Files: files | file ages | folders
SHA1:b99aa66d1f91abf5b01c793e5bbc7df2df98b0a0
User & Date: robert 2009-10-05 20:05:22
References
2009-10-10
10:06 Ticket [bfb8427c] Cloning and syncing an URL with no repository or misconfigured CGI repository fails silently. status still Open with 1 other change artifact: 82d4a349 user: anonymous
Context
2010-02-26
03:02
Merge in latest changes from trunk. Leaf check-in: df905727 user: linuxfood tags: creole
2009-10-05
20:05
add wiki-contents macro to creole parser, plus minor bug fix check-in: b99aa66d user: robert tags: creole
10:08
merge trunk into creole check-in: 651c75c5 user: robert tags: creole
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/creoleparser.c.

56
57
58
59
60
61
62

63





64
65
66

67
68
69
70
71
72
73
...
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
...
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
...
220
221
222
223
224
225
226

227
228
229
230
231
232
233
...
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
...
698
699
700
701
702
703
704













705
706
707
708
709
710
711
...
717
718
719
720
721
722
723





724
725
726
727
728
729
730
...
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
...
845
846
847
848
849
850
851





























852
853
854
855
856
857
858
...
975
976
977
978
979
980
981

982
983
984
985
986
987
988
...
999
1000
1001
1002
1003
1004
1005

1006
1007
1008
1009
1010
1011
1012
....
1036
1037
1038
1039
1040
1041
1042








































1043
1044
1045
1046
1047
1048
1049
#define KIND_ITALIC          0x0000800
#define KIND_SUPERSCRIPT     0x0001000
#define KIND_SUBSCRIPT       0x0002000
#define KIND_MONOSPACED      0x0004000
#define KIND_BREAK           0x0008000

#define KIND_TABLE_ROW       0x0010000

//}}}





//{{{ FLAG
// keep first four bits free
#define FLAG_CENTER   0x0000100

//}}}
struct Node {//{{{

  char *start;
  char *end;

  int kind;
................................................................................
  char *iend;

  int inLink;
  int inTable;
  int iesc;

  Blob *iblob;




};
//}}}

#endif

const int KIND_LIST = (KIND_UNORDERED_LIST | KIND_ORDERED_LIST);
................................................................................
        if (z[1] == '\n') {
          z[0] = ' ';
          return z + 2;
        }
        z[0] = '\n';
        return z + 1;

      case'\n':
        return z + 1;

      case '\t':
        z[0] = ' ';
        z++;
        break;

................................................................................
        p->lineWasBlank = 0;
        z++;
    }
  }
}
//}}}
//}}}


//{{{ INLINE PARSER

static int cr_isEsc(Parser *p){//{{{
  if (p->iesc){
    blob_append(p->iblob, p->icursor, 1);
    p->iesc = 0;
................................................................................
  if ((p->iend - p->icursor)<6) return 0;

  if (p->icursor[1]!='{' || p->icursor[2]!='{')
    return 0;

  char *s = p->icursor + 3;

  int count = p->iend - p->icursor - 6;
  while (count--){
    if (s[0]=='}' && s[1]=='}' && s[2]=='}' && s[3]!='}'){
      blob_appendf(p->iblob, "<tt class='creole-inline-nowiki'>%s</tt>", htmlize(p->icursor + 3, s - p->icursor-3));
      p->icursor = s + 3;
      return 1;
    }
    s++;
................................................................................

  }
  blob_append(p->iblob, "</table>", -1);
  p->inTable = 0;

}
//}}}














static void cr_render(Parser *p, Node *node){//{{{

  if (node->kind & KIND_PARAGRAPH){
    blob_append(p->iblob,   "\n<p>", -1);
    cr_parseInline(p, node->start, node->end );
    blob_append(p->iblob, "</p>\n", -1  );
................................................................................
        node->level,
        (node->flags & FLAG_CENTER) ? " style='text-align:center;'" : ""
    );
    cr_parseInline(p, node->start, node->end);
    blob_appendf(p->iblob, "</h%d>\n", node->level  );
    return;
  }






  if (node->kind & KIND_HORIZONTAL_RULE){
    blob_append(p->iblob, "<hr />", -1);
    return;
  }

  if (node->kind & KIND_LIST){
................................................................................
  char *s = p->cursor;
  if (memcmp(s, "<<fossil>>", 10)) return 0;
  p->this->start = s;
  p->this->kind = KIND_END_WIKI_MARKER;
  p->cursor += 10;
  return 1;
}
///}}}
static int isNoWikiBlock(Parser *p){//{{{

  char *s = p->cursor;

  if (s[0] != '{') return 0; s++;
  if (s[0] != '{') return 0; s++;
  if (s[0] != '{') return 0; s++;
................................................................................
  char *s = cr_nextLine(p, p->cursor);
  if (!p->lineWasBlank) return 0;

  p->cursor = s;
  p->this->kind = KIND_PARA_BREAK;
  return 1;
}





























//}}}
static int isHeading(Parser *p){//{{{

  char *s = cr_skipBlanks(p, p->cursor);

  int flags = 0;
  int level = cr_countChars(p, s, '=');
................................................................................
  s = cr_nextLine(p, s);
  p->cursor = p->this->end = s;
  p->this->kind = KIND_PARAGRAPH;
  return 1;

}
//}}}

static void cr_parse(Parser *p, char* z){//{{{

  p->previous = pool_new(p);
  p->previous->kind = KIND_PARA_BREAK;

  p->this = pool_new(p);
  p->this->kind = KIND_PARA_BREAK;
................................................................................
    while (1){

      // must be first
      if (isNoWikiBlock(p)) break;
      if (isParaBreak(p))   break;

      // order not important

      if (isHeading(p)) break;
      if (isHorizontalRule(p)) break;
      if (isListItem(p)) break;
      if (isTable(p)) break;

      // here for efficiency?
      if (isEndWikiMarker(p)) break;
................................................................................
    p->this = pool_new(p);

  }
}
//}}}

//}}}









































char *wiki_render_creole(Renderer *r, char *z){

  Parser parser;
  Parser *p = &parser;

  p->r = r;







>

>
>
>
>
>

|
|
>







 







<
<
<







 







|







 







>







 







|







 







>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>
>
>







 







|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>







 







>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
...
115
116
117
118
119
120
121



122
123
124
125
126
127
128
...
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
...
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
...
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
...
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
...
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
...
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
...
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
....
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
....
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
....
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
#define KIND_ITALIC          0x0000800
#define KIND_SUPERSCRIPT     0x0001000
#define KIND_SUBSCRIPT       0x0002000
#define KIND_MONOSPACED      0x0004000
#define KIND_BREAK           0x0008000

#define KIND_TABLE_ROW       0x0010000
#define KIND_MACRO           0X0020000
//}}}
//{{{ MACRO
#define MACRO_NONE           0X0000000
#define MACRO_FOSSIL         0x0000001
#define MACRO_WIKI_CONTENTS  0X0000002
//}}}
//{{{ FLAG
// keep first four bits free (why?:)
#define FLAG_CENTER      0x0000100
#define FLAG_MACRO_BLOCK 0X0000200
//}}}
struct Node {//{{{

  char *start;
  char *end;

  int kind;
................................................................................
  char *iend;

  int inLink;
  int inTable;
  int iesc;

  Blob *iblob;




};
//}}}

#endif

const int KIND_LIST = (KIND_UNORDERED_LIST | KIND_ORDERED_LIST);
................................................................................
        if (z[1] == '\n') {
          z[0] = ' ';
          return z + 2;
        }
        z[0] = '\n';
        return z + 1;

      case '\n':
        return z + 1;

      case '\t':
        z[0] = ' ';
        z++;
        break;

................................................................................
        p->lineWasBlank = 0;
        z++;
    }
  }
}
//}}}
//}}}


//{{{ INLINE PARSER

static int cr_isEsc(Parser *p){//{{{
  if (p->iesc){
    blob_append(p->iblob, p->icursor, 1);
    p->iesc = 0;
................................................................................
  if ((p->iend - p->icursor)<6) return 0;

  if (p->icursor[1]!='{' || p->icursor[2]!='{')
    return 0;

  char *s = p->icursor + 3;

  int count = p->iend - p->icursor - 3;
  while (count--){
    if (s[0]=='}' && s[1]=='}' && s[2]=='}' && s[3]!='}'){
      blob_appendf(p->iblob, "<tt class='creole-inline-nowiki'>%s</tt>", htmlize(p->icursor + 3, s - p->icursor-3));
      p->icursor = s + 3;
      return 1;
    }
    s++;
................................................................................

  }
  blob_append(p->iblob, "</table>", -1);
  p->inTable = 0;

}
//}}}

static void cr_renderMacro(Parser *p, Node *n){//{{{

  switch (n->level){

    case MACRO_WIKI_CONTENTS:
      do_macro_wiki_contents(p, n);
      break;

  }

}
//}}}

static void cr_render(Parser *p, Node *node){//{{{

  if (node->kind & KIND_PARAGRAPH){
    blob_append(p->iblob,   "\n<p>", -1);
    cr_parseInline(p, node->start, node->end );
    blob_append(p->iblob, "</p>\n", -1  );
................................................................................
        node->level,
        (node->flags & FLAG_CENTER) ? " style='text-align:center;'" : ""
    );
    cr_parseInline(p, node->start, node->end);
    blob_appendf(p->iblob, "</h%d>\n", node->level  );
    return;
  }

  if (node->kind & KIND_MACRO){
    cr_renderMacro(p, node);
    return;
  }

  if (node->kind & KIND_HORIZONTAL_RULE){
    blob_append(p->iblob, "<hr />", -1);
    return;
  }

  if (node->kind & KIND_LIST){
................................................................................
  char *s = p->cursor;
  if (memcmp(s, "<<fossil>>", 10)) return 0;
  p->this->start = s;
  p->this->kind = KIND_END_WIKI_MARKER;
  p->cursor += 10;
  return 1;
}
//}}}
static int isNoWikiBlock(Parser *p){//{{{

  char *s = p->cursor;

  if (s[0] != '{') return 0; s++;
  if (s[0] != '{') return 0; s++;
  if (s[0] != '{') return 0; s++;
................................................................................
  char *s = cr_nextLine(p, p->cursor);
  if (!p->lineWasBlank) return 0;

  p->cursor = s;
  p->this->kind = KIND_PARA_BREAK;
  return 1;
}
//}}}
static int isMacro(Parser *p){//{{{

  char *s = p->cursor;
  int macroId;
  int matchLength;

  if (s[0]!='<') return 0; s++;
  if (s[0]!='<') return 0; s++;
  if (s[0]=='<') return 0;

  matchLength = cr_has_macro(s, &macroId);
  if (!matchLength) return 0;

  s += matchLength;
  p->this->start = s;

  if (s[-1]!='>'){
    while (s[0] && s[1] && s[0]!='\n' && !(s[0]=='>' && s[1]=='>')) s++;
    if (!(s[0] == '>' && s[1] == '>')) return 0;
    s +=2;
  }
  p->cursor = s;
  p->this->kind = KIND_MACRO;
  p->this->level = macroId;
  p->this->flags &= FLAG_MACRO_BLOCK;
  p->this->end = s-2;
  return 1;
}
//}}}
static int isHeading(Parser *p){//{{{

  char *s = cr_skipBlanks(p, p->cursor);

  int flags = 0;
  int level = cr_countChars(p, s, '=');
................................................................................
  s = cr_nextLine(p, s);
  p->cursor = p->this->end = s;
  p->this->kind = KIND_PARAGRAPH;
  return 1;

}
//}}}

static void cr_parse(Parser *p, char* z){//{{{

  p->previous = pool_new(p);
  p->previous->kind = KIND_PARA_BREAK;

  p->this = pool_new(p);
  p->this->kind = KIND_PARA_BREAK;
................................................................................
    while (1){

      // must be first
      if (isNoWikiBlock(p)) break;
      if (isParaBreak(p))   break;

      // order not important
      if (isMacro(p)) break;
      if (isHeading(p)) break;
      if (isHorizontalRule(p)) break;
      if (isListItem(p)) break;
      if (isTable(p)) break;

      // here for efficiency?
      if (isEndWikiMarker(p)) break;
................................................................................
    p->this = pool_new(p);

  }
}
//}}}

//}}}

//{{{ MACROS
LOCAL void do_macro_wiki_contents(Parser *p, Node *n){//{{{

  Stmt q;

  blob_append(p->iblob, "<ul>", 4);

  db_prepare(&q,
    "SELECT substr(tagname, 6, 1000) FROM tag WHERE tagname GLOB 'wiki-*'"
    " ORDER BY lower(tagname)"
  );
  while( db_step(&q)==SQLITE_ROW ){
    const char *zName = db_column_text(&q, 0);
    blob_appendf(p->iblob, "<li><a href=\"%s/wiki?name=%T\">%h</a></li>", g.zBaseURL, zName, zName);
  }
  db_finalize(&q);
  blob_append(p->iblob, "</ul>", 5);
}//}}}


static int cr_match(char *z1, char *z2, int *len){
  *len = strlen(z2);
  return !memcmp(z1, z2 ,*len);
}

int cr_has_macro(char *z, int *tokenType){

  int len;

  if (cr_match(z, "wiki-contents>>", &len)) {
    *tokenType = MACRO_WIKI_CONTENTS;
    return len;
  }

  tokenType = MACRO_NONE;
  return 0;

}
//}}}

char *wiki_render_creole(Renderer *r, char *z){

  Parser parser;
  Parser *p = &parser;

  p->r = r;