Fossil SCM

Rename the "event artifact" type to "technical note" or "technote". The format of the artifact is unchanged. Add the ability to enter and edit technotes as markdown and plain text in addition to wiki.

drh 2015-02-14 17:56 trunk
Commit bd50848eb51d61dcc74c2af46a0b2c1199f99d24
3 files changed +140 -89 +10 -5 +30 -28
+140 -89
--- src/event.c
+++ src/event.c
@@ -15,78 +15,90 @@
1515
**
1616
*******************************************************************************
1717
**
1818
** This file contains code to do formatting of event messages:
1919
**
20
+** Technical Notes
2021
** Milestones
2122
** Blog posts
2223
** New articles
2324
** Process checkpoints
2425
** Announcements
26
+**
27
+** Do not confuse "event" artifacts with the "event" table in the
28
+** repository database. An "event" artifact is a technical-note: a
29
+** wiki- or blog-like essay that appears on the timeline. The "event"
30
+** table records all entries on the timeline, including tech-notes.
31
+**
32
+** (2015-02-14): Changing the name to "tech-note" most everywhere.
2533
*/
2634
#include "config.h"
2735
#include <assert.h>
2836
#include <ctype.h>
2937
#include "event.h"
3038
3139
/*
32
-** Output a hyperlink to an event given its tagid.
40
+** Output a hyperlink to an technote given its tagid.
3341
*/
3442
void hyperlink_to_event_tagid(int tagid){
35
- char *zEventId;
36
- zEventId = db_text(0, "SELECT substr(tagname, 7) FROM tag WHERE tagid=%d",
43
+ char *zId;
44
+ zId = db_text(0, "SELECT substr(tagname, 7) FROM tag WHERE tagid=%d",
3745
tagid);
38
- @ [%z(href("%R/event/%s",zEventId))%S(zEventId)</a>]
39
- free(zEventId);
46
+ @ [%z(href("%R/technote/%s",zId))%S(zId)</a>]
47
+ free(zId);
4048
}
4149
4250
/*
51
+** WEBPAGE: technote
4352
** WEBPAGE: event
44
-** URL: /event
53
+**
54
+** Display a "technical note" or "tech-note" (formerly called an "event").
55
+**
4556
** PARAMETERS:
4657
**
47
-** name=EVENTID // Identify the event to display EVENTID must be complete
48
-** aid=ARTIFACTID // Which specific version of the event. Optional.
49
-** v=BOOLEAN // Show details if TRUE. Default is FALSE. Optional.
58
+** name=ID // Identify the tech-note to display. ID must be complete
59
+** aid=ARTIFACTID // Which specific version of the tech-note. Optional.
60
+** v=BOOLEAN // Show details if TRUE. Default is FALSE. Optional.
5061
**
5162
** Display an existing event identified by EVENTID
5263
*/
5364
void event_page(void){
5465
int rid = 0; /* rid of the event artifact */
5566
char *zUuid; /* UUID corresponding to rid */
56
- const char *zEventId; /* Event identifier */
67
+ const char *zId; /* Event identifier */
5768
const char *zVerbose; /* Value of verbose option */
58
- char *zETime; /* Time of the event */
69
+ char *zETime; /* Time of the tech-note */
5970
char *zATime; /* Time the artifact was created */
6071
int specRid; /* rid specified by aid= parameter */
61
- int prevRid, nextRid; /* Previous or next edits of this event */
62
- Manifest *pEvent; /* Parsed event artifact */
63
- Blob fullbody; /* Complete content of the event body */
64
- Blob title; /* Title extracted from the event body */
72
+ int prevRid, nextRid; /* Previous or next edits of this tech-note */
73
+ Manifest *pTNote; /* Parsed technote artifact */
74
+ Blob fullbody; /* Complete content of the technote body */
75
+ Blob title; /* Title extracted from the technote body */
6576
Blob tail; /* Event body that comes after the title */
66
- Stmt q1; /* Query to search for the event */
77
+ Stmt q1; /* Query to search for the technote */
6778
int verboseFlag; /* True to show details */
79
+ const char *zMimetype = 0; /* Mimetype of the document */
6880
6981
70
- /* wiki-read privilege is needed in order to read events.
82
+ /* wiki-read privilege is needed in order to read tech-notes.
7183
*/
7284
login_check_credentials();
7385
if( !g.perm.RdWiki ){
7486
login_needed(g.anon.RdWiki);
7587
return;
7688
}
7789
78
- zEventId = P("name");
79
- if( zEventId==0 ){ fossil_redirect_home(); return; }
90
+ zId = P("name");
91
+ if( zId==0 ){ fossil_redirect_home(); return; }
8092
zUuid = (char*)P("aid");
8193
specRid = zUuid ? uuid_to_rid(zUuid, 0) : 0;
8294
rid = nextRid = prevRid = 0;
8395
db_prepare(&q1,
8496
"SELECT rid FROM tagxref"
8597
" WHERE tagid=(SELECT tagid FROM tag WHERE tagname GLOB 'event-%q*')"
8698
" ORDER BY mtime DESC",
87
- zEventId
99
+ zId
88100
);
89101
while( db_step(&q1)==SQLITE_ROW ){
90102
nextRid = rid;
91103
rid = db_column_int(&q1, 0);
92104
if( specRid==0 || specRid==rid ){
@@ -96,12 +108,12 @@
96108
break;
97109
}
98110
}
99111
db_finalize(&q1);
100112
if( rid==0 || (specRid!=0 && specRid!=rid) ){
101
- style_header("No Such Event");
102
- @ Cannot locate specified event
113
+ style_header("No Such Tech-Note");
114
+ @ Cannot locate a technical note called <b>%h(zId)</b>.
103115
style_footer();
104116
return;
105117
}
106118
zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
107119
zVerbose = P("v");
@@ -113,122 +125,150 @@
113125
}
114126
verboseFlag = (zVerbose!=0) && !is_false(zVerbose);
115127
116128
/* Extract the event content.
117129
*/
118
- pEvent = manifest_get(rid, CFTYPE_EVENT, 0);
119
- if( pEvent==0 ){
120
- fossil_fatal("Object #%d is not an event", rid);
130
+ pTNote = manifest_get(rid, CFTYPE_EVENT, 0);
131
+ if( pTNote==0 ){
132
+ fossil_fatal("Object #%d is not a tech-note", rid);
121133
}
122
- blob_init(&fullbody, pEvent->zWiki, -1);
123
- if( wiki_find_title(&fullbody, &title, &tail) ){
124
- style_header("%s", blob_str(&title));
134
+ zMimetype = wiki_filter_mimetypes(PD("mimetype",pTNote->zMimetype));
135
+ blob_init(&fullbody, pTNote->zWiki, -1);
136
+ blob_init(&title, 0, 0);
137
+ blob_init(&tail, 0, 0);
138
+ if( fossil_strcmp(zMimetype, "text/x-fossil-wiki")==0 ){
139
+ if( !wiki_find_title(&fullbody, &title, &tail) ){
140
+ blob_appendf(&title, "Tech-note %S", zId);
141
+ tail = fullbody;
142
+ }
143
+ }else if( fossil_strcmp(zMimetype, "text/x-markdown")==0 ){
144
+ markdown_to_html(&fullbody, &title, &tail);
145
+ if( blob_size(&title)==0 ){
146
+ blob_appendf(&title, "Tech-note %S", zId);
147
+ }
125148
}else{
126
- style_header("Event %S", zEventId);
149
+ blob_appendf(&title, "Tech-note %S", zId);
127150
tail = fullbody;
128151
}
152
+ style_header("%s", blob_str(&title));
129153
if( g.perm.WrWiki && g.perm.Write && nextRid==0 ){
130
- style_submenu_element("Edit", "Edit", "%s/eventedit?name=%s",
131
- g.zTop, zEventId);
154
+ style_submenu_element("Edit", 0, "%R/technoteedit?name=%!S", zId);
132155
}
133
- zETime = db_text(0, "SELECT datetime(%.17g)", pEvent->rEventDate);
134
- style_submenu_element("Context", 0, "%R/timeline?c=%.20s", zEventId);
156
+ zETime = db_text(0, "SELECT datetime(%.17g)", pTNote->rEventDate);
157
+ style_submenu_element("Context", 0, "%R/timeline?c=%.20s", zId);
135158
if( g.perm.Hyperlink ){
136159
if( verboseFlag ){
137
- style_submenu_element("Plain", 0, "%R/event?name=%.20s&aid=%s",
138
- zEventId, zUuid);
160
+ style_submenu_element("Plain", 0,
161
+ "%R/technote?name=%!S&aid=%s&mimetype=text/plain",
162
+ zId, zUuid);
139163
if( nextRid ){
140164
char *zNext;
141165
zNext = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nextRid);
142
- style_submenu_element("Next", 0,"%R/event?name=%.20s&aid=%s&v",
143
- zEventId, zNext);
166
+ style_submenu_element("Next", 0,"%R/technote?name=%!S&aid=%s&v",
167
+ zId, zNext);
144168
free(zNext);
145169
}
146170
if( prevRid ){
147171
char *zPrev;
148172
zPrev = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", prevRid);
149
- style_submenu_element("Prev", 0, "%R/event?name=%s&aid=%s&v",
150
- zEventId, zPrev);
173
+ style_submenu_element("Prev", 0, "%R/technote?name=%!S&aid=%s&v",
174
+ zId, zPrev);
151175
free(zPrev);
152176
}
153177
}else{
154
- style_submenu_element("Detail", 0, "%R/event?name=%.20s&aid=%s&v",
155
- zEventId, zUuid);
178
+ style_submenu_element("Detail", 0, "%R/technote?name=%!S&aid=%s&v",
179
+ zId, zUuid);
156180
}
157181
}
158182
159183
if( verboseFlag && g.perm.Hyperlink ){
160184
int i;
161185
const char *zClr = 0;
162186
Blob comment;
163187
164
- zATime = db_text(0, "SELECT datetime(%.17g)", pEvent->rDate);
165
- @ <p>Event [%z(href("%R/artifact/%!S",zUuid))%S(zUuid)</a>] at
188
+ zATime = db_text(0, "SELECT datetime(%.17g)", pTNote->rDate);
189
+ @ <p>Tech-note [%z(href("%R/artifact/%!S",zUuid))%S(zUuid)</a>] at
166190
@ [%z(href("%R/timeline?c=%T",zETime))%s(zETime)</a>]
167
- @ entered by user <b>%h(pEvent->zUser)</b> on
191
+ @ entered by user <b>%h(pTNote->zUser)</b> on
168192
@ [%z(href("%R/timeline?c=%T",zATime))%s(zATime)</a>]:</p>
169193
@ <blockquote>
170
- for(i=0; i<pEvent->nTag; i++){
171
- if( fossil_strcmp(pEvent->aTag[i].zName,"+bgcolor")==0 ){
172
- zClr = pEvent->aTag[i].zValue;
194
+ for(i=0; i<pTNote->nTag; i++){
195
+ if( fossil_strcmp(pTNote->aTag[i].zName,"+bgcolor")==0 ){
196
+ zClr = pTNote->aTag[i].zValue;
173197
}
174198
}
175199
if( zClr && zClr[0]==0 ) zClr = 0;
176200
if( zClr ){
177201
@ <div style="background-color: %h(zClr);">
178202
}else{
179203
@ <div>
180204
}
181
- blob_init(&comment, pEvent->zComment, -1);
205
+ blob_init(&comment, pTNote->zComment, -1);
182206
wiki_convert(&comment, 0, WIKI_INLINE);
183207
blob_reset(&comment);
184208
@ </div>
185209
@ </blockquote><hr />
186210
}
187211
188
- wiki_convert(&tail, 0, 0);
212
+ if( fossil_strcmp(zMimetype, "text/x-fossil-wiki")==0 ){
213
+ wiki_convert(&fullbody, 0, 0);
214
+ }else if( fossil_strcmp(zMimetype, "text/x-markdown")==0 ){
215
+ cgi_append_content(blob_buffer(&tail), blob_size(&tail));
216
+ }else{
217
+ @ <pre>
218
+ @ %h(blob_str(&fullbody))
219
+ @ </pre>
220
+ }
189221
style_footer();
190
- manifest_destroy(pEvent);
222
+ manifest_destroy(pTNote);
191223
}
192224
193225
/*
226
+** WEBPAGE: technoteedit
194227
** WEBPAGE: eventedit
195
-** URL: /eventedit?name=EVENTID
228
+**
229
+** Revise or create a technical note (formerly called an 'event').
230
+**
231
+** Parameters:
196232
**
197
-** Edit an event. If name is omitted, create a new event.
233
+** name=ID Hex hash ID of the tech-note. If omitted, a new
234
+** tech-note is created.
198235
*/
199236
void eventedit_page(void){
200237
char *zTag;
201238
int rid = 0;
202239
Blob event;
203
- const char *zEventId;
240
+ const char *zId;
204241
int n;
205242
const char *z;
206243
char *zBody = (char*)P("w");
207244
char *zETime = (char*)P("t");
208245
const char *zComment = P("c");
209246
const char *zTags = P("g");
210247
const char *zClr;
248
+ const char *zMimetype = P("mimetype");
249
+ int isNew = 0;
211250
212251
if( zBody ){
213252
zBody = mprintf("%s", zBody);
214253
}
215254
login_check_credentials();
216
- zEventId = P("name");
217
- if( zEventId==0 ){
218
- zEventId = db_text(0, "SELECT lower(hex(randomblob(20)))");
255
+ zId = P("name");
256
+ if( zId==0 ){
257
+ zId = db_text(0, "SELECT lower(hex(randomblob(20)))");
258
+ isNew = 1;
219259
}else{
220
- int nEventId = strlen(zEventId);
221
- if( nEventId!=40 || !validate16(zEventId, 40) ){
260
+ int nId = strlen(zId);
261
+ if( !validate16(zId, nId) ){
222262
fossil_redirect_home();
223263
return;
224264
}
225265
}
226
- zTag = mprintf("event-%s", zEventId);
266
+ zTag = mprintf("event-%s", zId);
227267
rid = db_int(0,
228268
"SELECT rid FROM tagxref"
229
- " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)"
269
+ " WHERE tagid=(SELECT tagid FROM tag WHERE tagname GLOB '%q*')"
230270
" ORDER BY mtime DESC", zTag
231271
);
232272
free(zTag);
233273
234274
/* Need both check-in and wiki-write or wiki-create privileges in order
@@ -239,30 +279,34 @@
239279
return;
240280
}
241281
242282
/* Figure out the color */
243283
if( rid ){
244
- zClr = db_text("", "SELECT bgcolor FROM event WHERE objid=%d", rid);
284
+ zClr = db_text("", "SELECT bgcolor FROM event WHERE objid=%d", rid);
245285
}else{
246286
zClr = "";
287
+ isNew = 1;
247288
}
248289
zClr = PD("clr",zClr);
249290
if( fossil_strcmp(zClr,"##")==0 ) zClr = PD("cclr","");
250291
251292
252293
/* If editing an existing event, extract the key fields to use as
253294
** a starting point for the edit.
254295
*/
255
- if( rid && (zBody==0 || zETime==0 || zComment==0 || zTags==0) ){
256
- Manifest *pEvent;
257
- pEvent = manifest_get(rid, CFTYPE_EVENT, 0);
258
- if( pEvent && pEvent->type==CFTYPE_EVENT ){
259
- if( zBody==0 ) zBody = pEvent->zWiki;
296
+ if( rid
297
+ && (zBody==0 || zETime==0 || zComment==0 || zTags==0 || zMimetype==0)
298
+ ){
299
+ Manifest *pTNote;
300
+ pTNote = manifest_get(rid, CFTYPE_EVENT, 0);
301
+ if( pTNote && pTNote->type==CFTYPE_EVENT ){
302
+ if( zBody==0 ) zBody = pTNote->zWiki;
260303
if( zETime==0 ){
261
- zETime = db_text(0, "SELECT datetime(%.17g)", pEvent->rEventDate);
304
+ zETime = db_text(0, "SELECT datetime(%.17g)", pTNote->rEventDate);
262305
}
263
- if( zComment==0 ) zComment = pEvent->zComment;
306
+ if( zComment==0 ) zComment = pTNote->zComment;
307
+ if( zMimetype==0 ) zMimetype = pTNote->zMimetype;
264308
}
265309
if( zTags==0 ){
266310
zTags = db_text(0,
267311
"SELECT group_concat(substr(tagname,5),', ')"
268312
" FROM tagxref, tag"
@@ -276,11 +320,11 @@
276320
zETime = db_text(0, "SELECT coalesce(datetime(%Q),datetime('now'))", zETime);
277321
if( P("submit")!=0 && (zBody!=0 && zComment!=0) ){
278322
char *zDate;
279323
Blob cksum;
280324
int nrid, n;
281
- blob_zero(&event);
325
+ blob_init(&event, 0, 0);
282326
db_begin_transaction();
283327
login_verify_csrf_secret();
284328
while( fossil_isspace(zComment[0]) ) zComment++;
285329
n = strlen(zComment);
286330
while( n>0 && fossil_isspace(zComment[n-1]) ){ n--; }
@@ -289,17 +333,20 @@
289333
}
290334
zDate = date_in_standard_format("now");
291335
blob_appendf(&event, "D %s\n", zDate);
292336
free(zDate);
293337
zETime[10] = 'T';
294
- blob_appendf(&event, "E %s %s\n", zETime, zEventId);
338
+ blob_appendf(&event, "E %s %s\n", zETime, zId);
295339
zETime[10] = ' ';
296340
if( rid ){
297341
char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
298342
blob_appendf(&event, "P %s\n", zUuid);
299343
free(zUuid);
300344
}
345
+ if( zMimetype && zMimetype[0] ){
346
+ blob_appendf(&event, "N %s\n", zMimetype);
347
+ }
301348
if( zClr && zClr[0] ){
302349
blob_appendf(&event, "T +bgcolor * %F\n", zClr);
303350
}
304351
if( zTags && zTags[0] ){
305352
Blob tags, one;
@@ -350,22 +397,26 @@
350397
db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nrid);
351398
manifest_crosslink(nrid, &event, MC_NONE);
352399
assert( blob_is_reset(&event) );
353400
content_deltify(rid, nrid, 0);
354401
db_end_transaction(0);
355
- cgi_redirectf("event?name=%T", zEventId);
402
+ cgi_redirectf("technote?name=%T", zId);
356403
}
357404
if( P("cancel")!=0 ){
358
- cgi_redirectf("event?name=%T", zEventId);
405
+ cgi_redirectf("technote?name=%T", zId);
359406
return;
360407
}
361408
if( zBody==0 ){
362
- zBody = mprintf("<i>Event Text</i>");
409
+ zBody = mprintf("Insert new content here...");
363410
}
364
- style_header("Edit Event %S", zEventId);
411
+ if( isNew ){
412
+ style_header("New Tech-note %S", zId);
413
+ }else{
414
+ style_header("Edit Tech-note %S", zId);
415
+ }
365416
if( P("preview")!=0 ){
366
- Blob title, tail, com;
417
+ Blob com;
367418
@ <p><b>Timeline comment preview:</b></p>
368419
@ <blockquote>
369420
@ <table border="0">
370421
if( zClr && zClr[0] ){
371422
@ <tr><td style="background-color: %h(zClr);">
@@ -377,55 +428,55 @@
377428
wiki_convert(&com, 0, WIKI_INLINE|WIKI_NOBADLINKS);
378429
@ </td></tr></table>
379430
@ </blockquote>
380431
@ <p><b>Page content preview:</b><p>
381432
@ <blockquote>
382
- blob_zero(&event);
433
+ blob_init(&event, 0, 0);
383434
blob_append(&event, zBody, -1);
384
- if( wiki_find_title(&event, &title, &tail) ){
385
- @ <h2 align="center">%h(blob_str(&title))</h2>
386
- wiki_convert(&tail, 0, 0);
387
- }else{
388
- wiki_convert(&event, 0, 0);
389
- }
435
+ wiki_render_by_mimetype(&event, zMimetype);
390436
@ </blockquote><hr />
391437
blob_reset(&event);
392438
}
393439
for(n=2, z=zBody; z[0]; z++){
394440
if( z[0]=='\n' ) n++;
395441
}
396442
if( n<20 ) n = 20;
397443
if( n>40 ) n = 40;
398
- @ <form method="post" action="%s(g.zTop)/eventedit"><div>
444
+ @ <form method="post" action="%R/technoteedit"><div>
399445
login_insert_csrf_secret();
400
- @ <input type="hidden" name="name" value="%h(zEventId)" />
446
+ @ <input type="hidden" name="name" value="%h(zId)" />
401447
@ <table border="0" cellspacing="10">
402448
403
- @ <tr><th align="right" valign="top">Event&nbsp;Time (UTC):</th>
449
+ @ <tr><th align="right" valign="top">Timestamp (UTC):</th>
404450
@ <td valign="top">
405451
@ <input type="text" name="t" size="25" value="%h(zETime)" />
406452
@ </td></tr>
407453
408
- @ <tr><th align="right" valign="top">Timeline&nbsp;Comment:</th>
454
+ @ <tr><th align="right" valign="top">Timeline Comment:</th>
409455
@ <td valign="top">
410
- @ <textarea name="c" class="eventedit" cols="80"
456
+ @ <textarea name="c" class="technoteedit" cols="80"
411457
@ rows="3" wrap="virtual">%h(zComment)</textarea>
412458
@ </td></tr>
413459
414
- @ <tr><th align="right" valign="top">Background&nbsp;Color:</th>
460
+ @ <tr><th align="right" valign="top">Timeline Background Color:</th>
415461
@ <td valign="top">
416462
render_color_chooser(0, zClr, 0, "clr", "cclr");
417463
@ </td></tr>
418464
419465
@ <tr><th align="right" valign="top">Tags:</th>
420466
@ <td valign="top">
421467
@ <input type="text" name="g" size="40" value="%h(zTags)" />
422468
@ </td></tr>
469
+
470
+ @ <tr><th align="right" valign="top">Markup Style:</th>
471
+ @ <td valign="top">
472
+ mimetype_option_menu(zMimetype);
473
+ @ </td></tr>
423474
424475
@ <tr><th align="right" valign="top">Page&nbsp;Content:</th>
425476
@ <td valign="top">
426
- @ <textarea name="w" class="eventedit" cols="80"
477
+ @ <textarea name="w" class="technoteedit" cols="80"
427478
@ rows="%d(n)" wrap="virtual">%h(zBody)</textarea>
428479
@ </td></tr>
429480
430481
@ <tr><td colspan="2">
431482
@ <input type="submit" name="preview" value="Preview Your Changes" />
432483
--- src/event.c
+++ src/event.c
@@ -15,78 +15,90 @@
15 **
16 *******************************************************************************
17 **
18 ** This file contains code to do formatting of event messages:
19 **
 
20 ** Milestones
21 ** Blog posts
22 ** New articles
23 ** Process checkpoints
24 ** Announcements
 
 
 
 
 
 
 
25 */
26 #include "config.h"
27 #include <assert.h>
28 #include <ctype.h>
29 #include "event.h"
30
31 /*
32 ** Output a hyperlink to an event given its tagid.
33 */
34 void hyperlink_to_event_tagid(int tagid){
35 char *zEventId;
36 zEventId = db_text(0, "SELECT substr(tagname, 7) FROM tag WHERE tagid=%d",
37 tagid);
38 @ [%z(href("%R/event/%s",zEventId))%S(zEventId)</a>]
39 free(zEventId);
40 }
41
42 /*
 
43 ** WEBPAGE: event
44 ** URL: /event
 
 
45 ** PARAMETERS:
46 **
47 ** name=EVENTID // Identify the event to display EVENTID must be complete
48 ** aid=ARTIFACTID // Which specific version of the event. Optional.
49 ** v=BOOLEAN // Show details if TRUE. Default is FALSE. Optional.
50 **
51 ** Display an existing event identified by EVENTID
52 */
53 void event_page(void){
54 int rid = 0; /* rid of the event artifact */
55 char *zUuid; /* UUID corresponding to rid */
56 const char *zEventId; /* Event identifier */
57 const char *zVerbose; /* Value of verbose option */
58 char *zETime; /* Time of the event */
59 char *zATime; /* Time the artifact was created */
60 int specRid; /* rid specified by aid= parameter */
61 int prevRid, nextRid; /* Previous or next edits of this event */
62 Manifest *pEvent; /* Parsed event artifact */
63 Blob fullbody; /* Complete content of the event body */
64 Blob title; /* Title extracted from the event body */
65 Blob tail; /* Event body that comes after the title */
66 Stmt q1; /* Query to search for the event */
67 int verboseFlag; /* True to show details */
 
68
69
70 /* wiki-read privilege is needed in order to read events.
71 */
72 login_check_credentials();
73 if( !g.perm.RdWiki ){
74 login_needed(g.anon.RdWiki);
75 return;
76 }
77
78 zEventId = P("name");
79 if( zEventId==0 ){ fossil_redirect_home(); return; }
80 zUuid = (char*)P("aid");
81 specRid = zUuid ? uuid_to_rid(zUuid, 0) : 0;
82 rid = nextRid = prevRid = 0;
83 db_prepare(&q1,
84 "SELECT rid FROM tagxref"
85 " WHERE tagid=(SELECT tagid FROM tag WHERE tagname GLOB 'event-%q*')"
86 " ORDER BY mtime DESC",
87 zEventId
88 );
89 while( db_step(&q1)==SQLITE_ROW ){
90 nextRid = rid;
91 rid = db_column_int(&q1, 0);
92 if( specRid==0 || specRid==rid ){
@@ -96,12 +108,12 @@
96 break;
97 }
98 }
99 db_finalize(&q1);
100 if( rid==0 || (specRid!=0 && specRid!=rid) ){
101 style_header("No Such Event");
102 @ Cannot locate specified event
103 style_footer();
104 return;
105 }
106 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
107 zVerbose = P("v");
@@ -113,122 +125,150 @@
113 }
114 verboseFlag = (zVerbose!=0) && !is_false(zVerbose);
115
116 /* Extract the event content.
117 */
118 pEvent = manifest_get(rid, CFTYPE_EVENT, 0);
119 if( pEvent==0 ){
120 fossil_fatal("Object #%d is not an event", rid);
121 }
122 blob_init(&fullbody, pEvent->zWiki, -1);
123 if( wiki_find_title(&fullbody, &title, &tail) ){
124 style_header("%s", blob_str(&title));
 
 
 
 
 
 
 
 
 
 
 
125 }else{
126 style_header("Event %S", zEventId);
127 tail = fullbody;
128 }
 
129 if( g.perm.WrWiki && g.perm.Write && nextRid==0 ){
130 style_submenu_element("Edit", "Edit", "%s/eventedit?name=%s",
131 g.zTop, zEventId);
132 }
133 zETime = db_text(0, "SELECT datetime(%.17g)", pEvent->rEventDate);
134 style_submenu_element("Context", 0, "%R/timeline?c=%.20s", zEventId);
135 if( g.perm.Hyperlink ){
136 if( verboseFlag ){
137 style_submenu_element("Plain", 0, "%R/event?name=%.20s&aid=%s",
138 zEventId, zUuid);
 
139 if( nextRid ){
140 char *zNext;
141 zNext = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nextRid);
142 style_submenu_element("Next", 0,"%R/event?name=%.20s&aid=%s&v",
143 zEventId, zNext);
144 free(zNext);
145 }
146 if( prevRid ){
147 char *zPrev;
148 zPrev = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", prevRid);
149 style_submenu_element("Prev", 0, "%R/event?name=%s&aid=%s&v",
150 zEventId, zPrev);
151 free(zPrev);
152 }
153 }else{
154 style_submenu_element("Detail", 0, "%R/event?name=%.20s&aid=%s&v",
155 zEventId, zUuid);
156 }
157 }
158
159 if( verboseFlag && g.perm.Hyperlink ){
160 int i;
161 const char *zClr = 0;
162 Blob comment;
163
164 zATime = db_text(0, "SELECT datetime(%.17g)", pEvent->rDate);
165 @ <p>Event [%z(href("%R/artifact/%!S",zUuid))%S(zUuid)</a>] at
166 @ [%z(href("%R/timeline?c=%T",zETime))%s(zETime)</a>]
167 @ entered by user <b>%h(pEvent->zUser)</b> on
168 @ [%z(href("%R/timeline?c=%T",zATime))%s(zATime)</a>]:</p>
169 @ <blockquote>
170 for(i=0; i<pEvent->nTag; i++){
171 if( fossil_strcmp(pEvent->aTag[i].zName,"+bgcolor")==0 ){
172 zClr = pEvent->aTag[i].zValue;
173 }
174 }
175 if( zClr && zClr[0]==0 ) zClr = 0;
176 if( zClr ){
177 @ <div style="background-color: %h(zClr);">
178 }else{
179 @ <div>
180 }
181 blob_init(&comment, pEvent->zComment, -1);
182 wiki_convert(&comment, 0, WIKI_INLINE);
183 blob_reset(&comment);
184 @ </div>
185 @ </blockquote><hr />
186 }
187
188 wiki_convert(&tail, 0, 0);
 
 
 
 
 
 
 
 
189 style_footer();
190 manifest_destroy(pEvent);
191 }
192
193 /*
 
194 ** WEBPAGE: eventedit
195 ** URL: /eventedit?name=EVENTID
 
 
 
196 **
197 ** Edit an event. If name is omitted, create a new event.
 
198 */
199 void eventedit_page(void){
200 char *zTag;
201 int rid = 0;
202 Blob event;
203 const char *zEventId;
204 int n;
205 const char *z;
206 char *zBody = (char*)P("w");
207 char *zETime = (char*)P("t");
208 const char *zComment = P("c");
209 const char *zTags = P("g");
210 const char *zClr;
 
 
211
212 if( zBody ){
213 zBody = mprintf("%s", zBody);
214 }
215 login_check_credentials();
216 zEventId = P("name");
217 if( zEventId==0 ){
218 zEventId = db_text(0, "SELECT lower(hex(randomblob(20)))");
 
219 }else{
220 int nEventId = strlen(zEventId);
221 if( nEventId!=40 || !validate16(zEventId, 40) ){
222 fossil_redirect_home();
223 return;
224 }
225 }
226 zTag = mprintf("event-%s", zEventId);
227 rid = db_int(0,
228 "SELECT rid FROM tagxref"
229 " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)"
230 " ORDER BY mtime DESC", zTag
231 );
232 free(zTag);
233
234 /* Need both check-in and wiki-write or wiki-create privileges in order
@@ -239,30 +279,34 @@
239 return;
240 }
241
242 /* Figure out the color */
243 if( rid ){
244 zClr = db_text("", "SELECT bgcolor FROM event WHERE objid=%d", rid);
245 }else{
246 zClr = "";
 
247 }
248 zClr = PD("clr",zClr);
249 if( fossil_strcmp(zClr,"##")==0 ) zClr = PD("cclr","");
250
251
252 /* If editing an existing event, extract the key fields to use as
253 ** a starting point for the edit.
254 */
255 if( rid && (zBody==0 || zETime==0 || zComment==0 || zTags==0) ){
256 Manifest *pEvent;
257 pEvent = manifest_get(rid, CFTYPE_EVENT, 0);
258 if( pEvent && pEvent->type==CFTYPE_EVENT ){
259 if( zBody==0 ) zBody = pEvent->zWiki;
 
 
260 if( zETime==0 ){
261 zETime = db_text(0, "SELECT datetime(%.17g)", pEvent->rEventDate);
262 }
263 if( zComment==0 ) zComment = pEvent->zComment;
 
264 }
265 if( zTags==0 ){
266 zTags = db_text(0,
267 "SELECT group_concat(substr(tagname,5),', ')"
268 " FROM tagxref, tag"
@@ -276,11 +320,11 @@
276 zETime = db_text(0, "SELECT coalesce(datetime(%Q),datetime('now'))", zETime);
277 if( P("submit")!=0 && (zBody!=0 && zComment!=0) ){
278 char *zDate;
279 Blob cksum;
280 int nrid, n;
281 blob_zero(&event);
282 db_begin_transaction();
283 login_verify_csrf_secret();
284 while( fossil_isspace(zComment[0]) ) zComment++;
285 n = strlen(zComment);
286 while( n>0 && fossil_isspace(zComment[n-1]) ){ n--; }
@@ -289,17 +333,20 @@
289 }
290 zDate = date_in_standard_format("now");
291 blob_appendf(&event, "D %s\n", zDate);
292 free(zDate);
293 zETime[10] = 'T';
294 blob_appendf(&event, "E %s %s\n", zETime, zEventId);
295 zETime[10] = ' ';
296 if( rid ){
297 char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
298 blob_appendf(&event, "P %s\n", zUuid);
299 free(zUuid);
300 }
 
 
 
301 if( zClr && zClr[0] ){
302 blob_appendf(&event, "T +bgcolor * %F\n", zClr);
303 }
304 if( zTags && zTags[0] ){
305 Blob tags, one;
@@ -350,22 +397,26 @@
350 db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nrid);
351 manifest_crosslink(nrid, &event, MC_NONE);
352 assert( blob_is_reset(&event) );
353 content_deltify(rid, nrid, 0);
354 db_end_transaction(0);
355 cgi_redirectf("event?name=%T", zEventId);
356 }
357 if( P("cancel")!=0 ){
358 cgi_redirectf("event?name=%T", zEventId);
359 return;
360 }
361 if( zBody==0 ){
362 zBody = mprintf("<i>Event Text</i>");
363 }
364 style_header("Edit Event %S", zEventId);
 
 
 
 
365 if( P("preview")!=0 ){
366 Blob title, tail, com;
367 @ <p><b>Timeline comment preview:</b></p>
368 @ <blockquote>
369 @ <table border="0">
370 if( zClr && zClr[0] ){
371 @ <tr><td style="background-color: %h(zClr);">
@@ -377,55 +428,55 @@
377 wiki_convert(&com, 0, WIKI_INLINE|WIKI_NOBADLINKS);
378 @ </td></tr></table>
379 @ </blockquote>
380 @ <p><b>Page content preview:</b><p>
381 @ <blockquote>
382 blob_zero(&event);
383 blob_append(&event, zBody, -1);
384 if( wiki_find_title(&event, &title, &tail) ){
385 @ <h2 align="center">%h(blob_str(&title))</h2>
386 wiki_convert(&tail, 0, 0);
387 }else{
388 wiki_convert(&event, 0, 0);
389 }
390 @ </blockquote><hr />
391 blob_reset(&event);
392 }
393 for(n=2, z=zBody; z[0]; z++){
394 if( z[0]=='\n' ) n++;
395 }
396 if( n<20 ) n = 20;
397 if( n>40 ) n = 40;
398 @ <form method="post" action="%s(g.zTop)/eventedit"><div>
399 login_insert_csrf_secret();
400 @ <input type="hidden" name="name" value="%h(zEventId)" />
401 @ <table border="0" cellspacing="10">
402
403 @ <tr><th align="right" valign="top">Event&nbsp;Time (UTC):</th>
404 @ <td valign="top">
405 @ <input type="text" name="t" size="25" value="%h(zETime)" />
406 @ </td></tr>
407
408 @ <tr><th align="right" valign="top">Timeline&nbsp;Comment:</th>
409 @ <td valign="top">
410 @ <textarea name="c" class="eventedit" cols="80"
411 @ rows="3" wrap="virtual">%h(zComment)</textarea>
412 @ </td></tr>
413
414 @ <tr><th align="right" valign="top">Background&nbsp;Color:</th>
415 @ <td valign="top">
416 render_color_chooser(0, zClr, 0, "clr", "cclr");
417 @ </td></tr>
418
419 @ <tr><th align="right" valign="top">Tags:</th>
420 @ <td valign="top">
421 @ <input type="text" name="g" size="40" value="%h(zTags)" />
422 @ </td></tr>
 
 
 
 
 
423
424 @ <tr><th align="right" valign="top">Page&nbsp;Content:</th>
425 @ <td valign="top">
426 @ <textarea name="w" class="eventedit" cols="80"
427 @ rows="%d(n)" wrap="virtual">%h(zBody)</textarea>
428 @ </td></tr>
429
430 @ <tr><td colspan="2">
431 @ <input type="submit" name="preview" value="Preview Your Changes" />
432
--- src/event.c
+++ src/event.c
@@ -15,78 +15,90 @@
15 **
16 *******************************************************************************
17 **
18 ** This file contains code to do formatting of event messages:
19 **
20 ** Technical Notes
21 ** Milestones
22 ** Blog posts
23 ** New articles
24 ** Process checkpoints
25 ** Announcements
26 **
27 ** Do not confuse "event" artifacts with the "event" table in the
28 ** repository database. An "event" artifact is a technical-note: a
29 ** wiki- or blog-like essay that appears on the timeline. The "event"
30 ** table records all entries on the timeline, including tech-notes.
31 **
32 ** (2015-02-14): Changing the name to "tech-note" most everywhere.
33 */
34 #include "config.h"
35 #include <assert.h>
36 #include <ctype.h>
37 #include "event.h"
38
39 /*
40 ** Output a hyperlink to an technote given its tagid.
41 */
42 void hyperlink_to_event_tagid(int tagid){
43 char *zId;
44 zId = db_text(0, "SELECT substr(tagname, 7) FROM tag WHERE tagid=%d",
45 tagid);
46 @ [%z(href("%R/technote/%s",zId))%S(zId)</a>]
47 free(zId);
48 }
49
50 /*
51 ** WEBPAGE: technote
52 ** WEBPAGE: event
53 **
54 ** Display a "technical note" or "tech-note" (formerly called an "event").
55 **
56 ** PARAMETERS:
57 **
58 ** name=ID // Identify the tech-note to display. ID must be complete
59 ** aid=ARTIFACTID // Which specific version of the tech-note. Optional.
60 ** v=BOOLEAN // Show details if TRUE. Default is FALSE. Optional.
61 **
62 ** Display an existing event identified by EVENTID
63 */
64 void event_page(void){
65 int rid = 0; /* rid of the event artifact */
66 char *zUuid; /* UUID corresponding to rid */
67 const char *zId; /* Event identifier */
68 const char *zVerbose; /* Value of verbose option */
69 char *zETime; /* Time of the tech-note */
70 char *zATime; /* Time the artifact was created */
71 int specRid; /* rid specified by aid= parameter */
72 int prevRid, nextRid; /* Previous or next edits of this tech-note */
73 Manifest *pTNote; /* Parsed technote artifact */
74 Blob fullbody; /* Complete content of the technote body */
75 Blob title; /* Title extracted from the technote body */
76 Blob tail; /* Event body that comes after the title */
77 Stmt q1; /* Query to search for the technote */
78 int verboseFlag; /* True to show details */
79 const char *zMimetype = 0; /* Mimetype of the document */
80
81
82 /* wiki-read privilege is needed in order to read tech-notes.
83 */
84 login_check_credentials();
85 if( !g.perm.RdWiki ){
86 login_needed(g.anon.RdWiki);
87 return;
88 }
89
90 zId = P("name");
91 if( zId==0 ){ fossil_redirect_home(); return; }
92 zUuid = (char*)P("aid");
93 specRid = zUuid ? uuid_to_rid(zUuid, 0) : 0;
94 rid = nextRid = prevRid = 0;
95 db_prepare(&q1,
96 "SELECT rid FROM tagxref"
97 " WHERE tagid=(SELECT tagid FROM tag WHERE tagname GLOB 'event-%q*')"
98 " ORDER BY mtime DESC",
99 zId
100 );
101 while( db_step(&q1)==SQLITE_ROW ){
102 nextRid = rid;
103 rid = db_column_int(&q1, 0);
104 if( specRid==0 || specRid==rid ){
@@ -96,12 +108,12 @@
108 break;
109 }
110 }
111 db_finalize(&q1);
112 if( rid==0 || (specRid!=0 && specRid!=rid) ){
113 style_header("No Such Tech-Note");
114 @ Cannot locate a technical note called <b>%h(zId)</b>.
115 style_footer();
116 return;
117 }
118 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
119 zVerbose = P("v");
@@ -113,122 +125,150 @@
125 }
126 verboseFlag = (zVerbose!=0) && !is_false(zVerbose);
127
128 /* Extract the event content.
129 */
130 pTNote = manifest_get(rid, CFTYPE_EVENT, 0);
131 if( pTNote==0 ){
132 fossil_fatal("Object #%d is not a tech-note", rid);
133 }
134 zMimetype = wiki_filter_mimetypes(PD("mimetype",pTNote->zMimetype));
135 blob_init(&fullbody, pTNote->zWiki, -1);
136 blob_init(&title, 0, 0);
137 blob_init(&tail, 0, 0);
138 if( fossil_strcmp(zMimetype, "text/x-fossil-wiki")==0 ){
139 if( !wiki_find_title(&fullbody, &title, &tail) ){
140 blob_appendf(&title, "Tech-note %S", zId);
141 tail = fullbody;
142 }
143 }else if( fossil_strcmp(zMimetype, "text/x-markdown")==0 ){
144 markdown_to_html(&fullbody, &title, &tail);
145 if( blob_size(&title)==0 ){
146 blob_appendf(&title, "Tech-note %S", zId);
147 }
148 }else{
149 blob_appendf(&title, "Tech-note %S", zId);
150 tail = fullbody;
151 }
152 style_header("%s", blob_str(&title));
153 if( g.perm.WrWiki && g.perm.Write && nextRid==0 ){
154 style_submenu_element("Edit", 0, "%R/technoteedit?name=%!S", zId);
 
155 }
156 zETime = db_text(0, "SELECT datetime(%.17g)", pTNote->rEventDate);
157 style_submenu_element("Context", 0, "%R/timeline?c=%.20s", zId);
158 if( g.perm.Hyperlink ){
159 if( verboseFlag ){
160 style_submenu_element("Plain", 0,
161 "%R/technote?name=%!S&aid=%s&mimetype=text/plain",
162 zId, zUuid);
163 if( nextRid ){
164 char *zNext;
165 zNext = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nextRid);
166 style_submenu_element("Next", 0,"%R/technote?name=%!S&aid=%s&v",
167 zId, zNext);
168 free(zNext);
169 }
170 if( prevRid ){
171 char *zPrev;
172 zPrev = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", prevRid);
173 style_submenu_element("Prev", 0, "%R/technote?name=%!S&aid=%s&v",
174 zId, zPrev);
175 free(zPrev);
176 }
177 }else{
178 style_submenu_element("Detail", 0, "%R/technote?name=%!S&aid=%s&v",
179 zId, zUuid);
180 }
181 }
182
183 if( verboseFlag && g.perm.Hyperlink ){
184 int i;
185 const char *zClr = 0;
186 Blob comment;
187
188 zATime = db_text(0, "SELECT datetime(%.17g)", pTNote->rDate);
189 @ <p>Tech-note [%z(href("%R/artifact/%!S",zUuid))%S(zUuid)</a>] at
190 @ [%z(href("%R/timeline?c=%T",zETime))%s(zETime)</a>]
191 @ entered by user <b>%h(pTNote->zUser)</b> on
192 @ [%z(href("%R/timeline?c=%T",zATime))%s(zATime)</a>]:</p>
193 @ <blockquote>
194 for(i=0; i<pTNote->nTag; i++){
195 if( fossil_strcmp(pTNote->aTag[i].zName,"+bgcolor")==0 ){
196 zClr = pTNote->aTag[i].zValue;
197 }
198 }
199 if( zClr && zClr[0]==0 ) zClr = 0;
200 if( zClr ){
201 @ <div style="background-color: %h(zClr);">
202 }else{
203 @ <div>
204 }
205 blob_init(&comment, pTNote->zComment, -1);
206 wiki_convert(&comment, 0, WIKI_INLINE);
207 blob_reset(&comment);
208 @ </div>
209 @ </blockquote><hr />
210 }
211
212 if( fossil_strcmp(zMimetype, "text/x-fossil-wiki")==0 ){
213 wiki_convert(&fullbody, 0, 0);
214 }else if( fossil_strcmp(zMimetype, "text/x-markdown")==0 ){
215 cgi_append_content(blob_buffer(&tail), blob_size(&tail));
216 }else{
217 @ <pre>
218 @ %h(blob_str(&fullbody))
219 @ </pre>
220 }
221 style_footer();
222 manifest_destroy(pTNote);
223 }
224
225 /*
226 ** WEBPAGE: technoteedit
227 ** WEBPAGE: eventedit
228 **
229 ** Revise or create a technical note (formerly called an 'event').
230 **
231 ** Parameters:
232 **
233 ** name=ID Hex hash ID of the tech-note. If omitted, a new
234 ** tech-note is created.
235 */
236 void eventedit_page(void){
237 char *zTag;
238 int rid = 0;
239 Blob event;
240 const char *zId;
241 int n;
242 const char *z;
243 char *zBody = (char*)P("w");
244 char *zETime = (char*)P("t");
245 const char *zComment = P("c");
246 const char *zTags = P("g");
247 const char *zClr;
248 const char *zMimetype = P("mimetype");
249 int isNew = 0;
250
251 if( zBody ){
252 zBody = mprintf("%s", zBody);
253 }
254 login_check_credentials();
255 zId = P("name");
256 if( zId==0 ){
257 zId = db_text(0, "SELECT lower(hex(randomblob(20)))");
258 isNew = 1;
259 }else{
260 int nId = strlen(zId);
261 if( !validate16(zId, nId) ){
262 fossil_redirect_home();
263 return;
264 }
265 }
266 zTag = mprintf("event-%s", zId);
267 rid = db_int(0,
268 "SELECT rid FROM tagxref"
269 " WHERE tagid=(SELECT tagid FROM tag WHERE tagname GLOB '%q*')"
270 " ORDER BY mtime DESC", zTag
271 );
272 free(zTag);
273
274 /* Need both check-in and wiki-write or wiki-create privileges in order
@@ -239,30 +279,34 @@
279 return;
280 }
281
282 /* Figure out the color */
283 if( rid ){
284 zClr = db_text("", "SELECT bgcolor FROM event WHERE objid=%d", rid);
285 }else{
286 zClr = "";
287 isNew = 1;
288 }
289 zClr = PD("clr",zClr);
290 if( fossil_strcmp(zClr,"##")==0 ) zClr = PD("cclr","");
291
292
293 /* If editing an existing event, extract the key fields to use as
294 ** a starting point for the edit.
295 */
296 if( rid
297 && (zBody==0 || zETime==0 || zComment==0 || zTags==0 || zMimetype==0)
298 ){
299 Manifest *pTNote;
300 pTNote = manifest_get(rid, CFTYPE_EVENT, 0);
301 if( pTNote && pTNote->type==CFTYPE_EVENT ){
302 if( zBody==0 ) zBody = pTNote->zWiki;
303 if( zETime==0 ){
304 zETime = db_text(0, "SELECT datetime(%.17g)", pTNote->rEventDate);
305 }
306 if( zComment==0 ) zComment = pTNote->zComment;
307 if( zMimetype==0 ) zMimetype = pTNote->zMimetype;
308 }
309 if( zTags==0 ){
310 zTags = db_text(0,
311 "SELECT group_concat(substr(tagname,5),', ')"
312 " FROM tagxref, tag"
@@ -276,11 +320,11 @@
320 zETime = db_text(0, "SELECT coalesce(datetime(%Q),datetime('now'))", zETime);
321 if( P("submit")!=0 && (zBody!=0 && zComment!=0) ){
322 char *zDate;
323 Blob cksum;
324 int nrid, n;
325 blob_init(&event, 0, 0);
326 db_begin_transaction();
327 login_verify_csrf_secret();
328 while( fossil_isspace(zComment[0]) ) zComment++;
329 n = strlen(zComment);
330 while( n>0 && fossil_isspace(zComment[n-1]) ){ n--; }
@@ -289,17 +333,20 @@
333 }
334 zDate = date_in_standard_format("now");
335 blob_appendf(&event, "D %s\n", zDate);
336 free(zDate);
337 zETime[10] = 'T';
338 blob_appendf(&event, "E %s %s\n", zETime, zId);
339 zETime[10] = ' ';
340 if( rid ){
341 char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
342 blob_appendf(&event, "P %s\n", zUuid);
343 free(zUuid);
344 }
345 if( zMimetype && zMimetype[0] ){
346 blob_appendf(&event, "N %s\n", zMimetype);
347 }
348 if( zClr && zClr[0] ){
349 blob_appendf(&event, "T +bgcolor * %F\n", zClr);
350 }
351 if( zTags && zTags[0] ){
352 Blob tags, one;
@@ -350,22 +397,26 @@
397 db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nrid);
398 manifest_crosslink(nrid, &event, MC_NONE);
399 assert( blob_is_reset(&event) );
400 content_deltify(rid, nrid, 0);
401 db_end_transaction(0);
402 cgi_redirectf("technote?name=%T", zId);
403 }
404 if( P("cancel")!=0 ){
405 cgi_redirectf("technote?name=%T", zId);
406 return;
407 }
408 if( zBody==0 ){
409 zBody = mprintf("Insert new content here...");
410 }
411 if( isNew ){
412 style_header("New Tech-note %S", zId);
413 }else{
414 style_header("Edit Tech-note %S", zId);
415 }
416 if( P("preview")!=0 ){
417 Blob com;
418 @ <p><b>Timeline comment preview:</b></p>
419 @ <blockquote>
420 @ <table border="0">
421 if( zClr && zClr[0] ){
422 @ <tr><td style="background-color: %h(zClr);">
@@ -377,55 +428,55 @@
428 wiki_convert(&com, 0, WIKI_INLINE|WIKI_NOBADLINKS);
429 @ </td></tr></table>
430 @ </blockquote>
431 @ <p><b>Page content preview:</b><p>
432 @ <blockquote>
433 blob_init(&event, 0, 0);
434 blob_append(&event, zBody, -1);
435 wiki_render_by_mimetype(&event, zMimetype);
 
 
 
 
 
436 @ </blockquote><hr />
437 blob_reset(&event);
438 }
439 for(n=2, z=zBody; z[0]; z++){
440 if( z[0]=='\n' ) n++;
441 }
442 if( n<20 ) n = 20;
443 if( n>40 ) n = 40;
444 @ <form method="post" action="%R/technoteedit"><div>
445 login_insert_csrf_secret();
446 @ <input type="hidden" name="name" value="%h(zId)" />
447 @ <table border="0" cellspacing="10">
448
449 @ <tr><th align="right" valign="top">Timestamp (UTC):</th>
450 @ <td valign="top">
451 @ <input type="text" name="t" size="25" value="%h(zETime)" />
452 @ </td></tr>
453
454 @ <tr><th align="right" valign="top">Timeline Comment:</th>
455 @ <td valign="top">
456 @ <textarea name="c" class="technoteedit" cols="80"
457 @ rows="3" wrap="virtual">%h(zComment)</textarea>
458 @ </td></tr>
459
460 @ <tr><th align="right" valign="top">Timeline Background Color:</th>
461 @ <td valign="top">
462 render_color_chooser(0, zClr, 0, "clr", "cclr");
463 @ </td></tr>
464
465 @ <tr><th align="right" valign="top">Tags:</th>
466 @ <td valign="top">
467 @ <input type="text" name="g" size="40" value="%h(zTags)" />
468 @ </td></tr>
469
470 @ <tr><th align="right" valign="top">Markup Style:</th>
471 @ <td valign="top">
472 mimetype_option_menu(zMimetype);
473 @ </td></tr>
474
475 @ <tr><th align="right" valign="top">Page&nbsp;Content:</th>
476 @ <td valign="top">
477 @ <textarea name="w" class="technoteedit" cols="80"
478 @ rows="%d(n)" wrap="virtual">%h(zBody)</textarea>
479 @ </td></tr>
480
481 @ <tr><td colspan="2">
482 @ <input type="submit" name="preview" value="Preview Your Changes" />
483
+10 -5
--- src/wiki.c
+++ src/wiki.c
@@ -134,11 +134,15 @@
134134
}
135135
return "text/x-fossil-wiki";
136136
}
137137
138138
/*
139
-** Render wiki text according to its mimetype
139
+** Render wiki text according to its mimetype.
140
+**
141
+** text/x-fossil-wiki Fossil wiki
142
+** text/x-markdown Markdown
143
+** anything else... Plain text
140144
*/
141145
void wiki_render_by_mimetype(Blob *pWiki, const char *zMimetype){
142146
if( zMimetype==0 || fossil_strcmp(zMimetype, "text/x-fossil-wiki")==0 ){
143147
wiki_convert(pWiki, 0, 0);
144148
}else if( fossil_strcmp(zMimetype, "text/x-markdown")==0 ){
@@ -264,11 +268,11 @@
264268
@ <li> Use the %z(href("%R/wiki?name=Sandbox"))Sandbox</a>
265269
@ to experiment.</li>
266270
if( g.anon.NewWiki ){
267271
@ <li> Create a %z(href("%R/wikinew"))new wiki page</a>.</li>
268272
if( g.anon.Write ){
269
- @ <li> Create a %z(href("%R/eventedit"))new tech-note</a>.</li>
273
+ @ <li> Create a %z(href("%R/technoteedit"))new tech-note</a>.</li>
270274
}
271275
}
272276
@ <li> %z(href("%R/wcontent"))List of All Wiki Pages</a>
273277
@ available on this server.</li>
274278
if( g.anon.ModWiki ){
@@ -423,13 +427,13 @@
423427
424428
/*
425429
** Output a selection box from which the user can select the
426430
** wiki mimetype.
427431
*/
428
-static void mimetype_option_menu(const char *zMimetype){
432
+void mimetype_option_menu(const char *zMimetype){
429433
unsigned i;
430
- @ Markup style: <select name="mimetype" size="1">
434
+ @ <select name="mimetype" size="1">
431435
for(i=0; i<sizeof(azStyles)/sizeof(azStyles[0]); i+=2){
432436
if( fossil_strcmp(zMimetype,azStyles[i])==0 ){
433437
@ <option value="%s(azStyles[i])" selected>%s(azStyles[i+1])</option>
434438
}else{
435439
@ <option value="%s(azStyles[i])">%s(azStyles[i+1])</option>
@@ -573,11 +577,11 @@
573577
if( n<20 ) n = 20;
574578
if( n>30 ) n = 30;
575579
if( !isWysiwyg ){
576580
/* Traditional markup-only editing */
577581
form_begin(0, "%R/wikiedit");
578
- @ <div>
582
+ @ <div>Markup style:
579583
mimetype_option_menu(zMimetype);
580584
@ <br /><textarea name="w" class="wikiedit" cols="80"
581585
@ rows="%d(n)" wrap="virtual">%h(zBody)</textarea>
582586
@ <br />
583587
if( db_get_boolean("wysiwyg-wiki", 0) ){
@@ -646,10 +650,11 @@
646650
@ <p>Rules for wiki page names:</p>
647651
well_formed_wiki_name_rules();
648652
form_begin(0, "%R/wikinew");
649653
@ <p>Name of new wiki page:
650654
@ <input style="width: 35;" type="text" name="name" value="%h(zName)" /><br />
655
+ @ Markup style:
651656
mimetype_option_menu("text/x-fossil-wiki");
652657
@ <br /><input type="submit" value="Create" />
653658
@ </p></form>
654659
if( zName[0] ){
655660
@ <p><span class="wikiError">
656661
--- src/wiki.c
+++ src/wiki.c
@@ -134,11 +134,15 @@
134 }
135 return "text/x-fossil-wiki";
136 }
137
138 /*
139 ** Render wiki text according to its mimetype
 
 
 
 
140 */
141 void wiki_render_by_mimetype(Blob *pWiki, const char *zMimetype){
142 if( zMimetype==0 || fossil_strcmp(zMimetype, "text/x-fossil-wiki")==0 ){
143 wiki_convert(pWiki, 0, 0);
144 }else if( fossil_strcmp(zMimetype, "text/x-markdown")==0 ){
@@ -264,11 +268,11 @@
264 @ <li> Use the %z(href("%R/wiki?name=Sandbox"))Sandbox</a>
265 @ to experiment.</li>
266 if( g.anon.NewWiki ){
267 @ <li> Create a %z(href("%R/wikinew"))new wiki page</a>.</li>
268 if( g.anon.Write ){
269 @ <li> Create a %z(href("%R/eventedit"))new tech-note</a>.</li>
270 }
271 }
272 @ <li> %z(href("%R/wcontent"))List of All Wiki Pages</a>
273 @ available on this server.</li>
274 if( g.anon.ModWiki ){
@@ -423,13 +427,13 @@
423
424 /*
425 ** Output a selection box from which the user can select the
426 ** wiki mimetype.
427 */
428 static void mimetype_option_menu(const char *zMimetype){
429 unsigned i;
430 @ Markup style: <select name="mimetype" size="1">
431 for(i=0; i<sizeof(azStyles)/sizeof(azStyles[0]); i+=2){
432 if( fossil_strcmp(zMimetype,azStyles[i])==0 ){
433 @ <option value="%s(azStyles[i])" selected>%s(azStyles[i+1])</option>
434 }else{
435 @ <option value="%s(azStyles[i])">%s(azStyles[i+1])</option>
@@ -573,11 +577,11 @@
573 if( n<20 ) n = 20;
574 if( n>30 ) n = 30;
575 if( !isWysiwyg ){
576 /* Traditional markup-only editing */
577 form_begin(0, "%R/wikiedit");
578 @ <div>
579 mimetype_option_menu(zMimetype);
580 @ <br /><textarea name="w" class="wikiedit" cols="80"
581 @ rows="%d(n)" wrap="virtual">%h(zBody)</textarea>
582 @ <br />
583 if( db_get_boolean("wysiwyg-wiki", 0) ){
@@ -646,10 +650,11 @@
646 @ <p>Rules for wiki page names:</p>
647 well_formed_wiki_name_rules();
648 form_begin(0, "%R/wikinew");
649 @ <p>Name of new wiki page:
650 @ <input style="width: 35;" type="text" name="name" value="%h(zName)" /><br />
 
651 mimetype_option_menu("text/x-fossil-wiki");
652 @ <br /><input type="submit" value="Create" />
653 @ </p></form>
654 if( zName[0] ){
655 @ <p><span class="wikiError">
656
--- src/wiki.c
+++ src/wiki.c
@@ -134,11 +134,15 @@
134 }
135 return "text/x-fossil-wiki";
136 }
137
138 /*
139 ** Render wiki text according to its mimetype.
140 **
141 ** text/x-fossil-wiki Fossil wiki
142 ** text/x-markdown Markdown
143 ** anything else... Plain text
144 */
145 void wiki_render_by_mimetype(Blob *pWiki, const char *zMimetype){
146 if( zMimetype==0 || fossil_strcmp(zMimetype, "text/x-fossil-wiki")==0 ){
147 wiki_convert(pWiki, 0, 0);
148 }else if( fossil_strcmp(zMimetype, "text/x-markdown")==0 ){
@@ -264,11 +268,11 @@
268 @ <li> Use the %z(href("%R/wiki?name=Sandbox"))Sandbox</a>
269 @ to experiment.</li>
270 if( g.anon.NewWiki ){
271 @ <li> Create a %z(href("%R/wikinew"))new wiki page</a>.</li>
272 if( g.anon.Write ){
273 @ <li> Create a %z(href("%R/technoteedit"))new tech-note</a>.</li>
274 }
275 }
276 @ <li> %z(href("%R/wcontent"))List of All Wiki Pages</a>
277 @ available on this server.</li>
278 if( g.anon.ModWiki ){
@@ -423,13 +427,13 @@
427
428 /*
429 ** Output a selection box from which the user can select the
430 ** wiki mimetype.
431 */
432 void mimetype_option_menu(const char *zMimetype){
433 unsigned i;
434 @ <select name="mimetype" size="1">
435 for(i=0; i<sizeof(azStyles)/sizeof(azStyles[0]); i+=2){
436 if( fossil_strcmp(zMimetype,azStyles[i])==0 ){
437 @ <option value="%s(azStyles[i])" selected>%s(azStyles[i+1])</option>
438 }else{
439 @ <option value="%s(azStyles[i])">%s(azStyles[i+1])</option>
@@ -573,11 +577,11 @@
577 if( n<20 ) n = 20;
578 if( n>30 ) n = 30;
579 if( !isWysiwyg ){
580 /* Traditional markup-only editing */
581 form_begin(0, "%R/wikiedit");
582 @ <div>Markup style:
583 mimetype_option_menu(zMimetype);
584 @ <br /><textarea name="w" class="wikiedit" cols="80"
585 @ rows="%d(n)" wrap="virtual">%h(zBody)</textarea>
586 @ <br />
587 if( db_get_boolean("wysiwyg-wiki", 0) ){
@@ -646,10 +650,11 @@
650 @ <p>Rules for wiki page names:</p>
651 well_formed_wiki_name_rules();
652 form_begin(0, "%R/wikinew");
653 @ <p>Name of new wiki page:
654 @ <input style="width: 35;" type="text" name="name" value="%h(zName)" /><br />
655 @ Markup style:
656 mimetype_option_menu("text/x-fossil-wiki");
657 @ <br /><input type="submit" value="Create" />
658 @ </p></form>
659 if( zName[0] ){
660 @ <p><span class="wikiError">
661
--- www/fileformat.wiki
+++ www/fileformat.wiki
@@ -43,11 +43,11 @@
4343
<li> [#cluster | Clusters] </li>
4444
<li> [#ctrl | Control Artifacts] </li>
4545
<li> [#wikichng | Wiki Pages] </li>
4646
<li> [#tktchng | Ticket Changes] </li>
4747
<li> [#attachment | Attachments] </li>
48
-<li> [#event | Events] </li>
48
+<li> [#event | TechNotes] </li>
4949
</ul>
5050
5151
These seven artifact types are described in the following sections.
5252
5353
In the current implementation (as of 2009-01-25) the artifacts that
@@ -423,11 +423,12 @@
423423
424424
<a name="attachment"></a>
425425
<h2>6.0 Attachments</h2>
426426
427427
An attachment artifact associates some other artifact that is the
428
-attachment (the source artifact) with a ticket or wiki page or event to which
428
+attachment (the source artifact) with a ticket or wiki page or
429
+technical note to which
429430
the attachment is connected (the target artifact).
430431
The following cards are allowed on an attachment artifact:
431432
432433
<blockquote>
433434
<b>A</b> <i>filename target</i> ?<i>source</i>?<br />
@@ -437,12 +438,12 @@
437438
<b>U</b> <i>user-name</i><br />
438439
<b>Z</b> <i>checksum</i>
439440
</blockquote>
440441
441442
The A card specifies a filename for the attachment in its first argument.
442
-The second argument to the A card is the name
443
-of the wiki page or ticket or event to which the attachment is connected. The
443
+The second argument to the A card is the name of the wiki page or
444
+ticket or technical note to which the attachment is connected. The
444445
third argument is either missing or else it is the 40-character artifact
445446
ID of the attachment itself. A missing third argument means that the
446447
attachment should be deleted.
447448
448449
The C card is an optional comment describing what the attachment is about.
@@ -461,72 +462,73 @@
461462
The Z card is the usual checksum over the rest of the attachment artifact.
462463
The Z card is required.
463464
464465
465466
<a name="event"></a>
466
-<h2>7.0 Events</h2>
467
+<h2>7.0 Technical Notes</h2>
467468
468
-An event artifact associates a timeline comment and a page of text
469
-(similar to a wiki page) with a point in time. Events can be used
469
+A technical note or "technote" artifact (formerly known as an "event" artifact)
470
+associates a timeline comment and a page of text
471
+(similar to a wiki page) with a point in time. Technotes can be used
470472
to record project milestones, release notes, blog entries, process
471473
checkpoints, or news articles.
472
-The following cards are allowed on an event artifact:
474
+The following cards are allowed on an technote artifact:
473475
474476
<blockquote>
475477
<b>C</b> <i>comment</i><br>
476478
<b>D</b> <i>time-and-date-stamp</i><br />
477
-<b>E</b> <i>event-time</i> <i>event-id</i><br />
479
+<b>E</b> <i>technote-time</i> <i>technote-id</i><br />
478480
<b>N</b> <i>mimetype</i><br />
479481
<b>P</b> <i>parent-artifact-id</i>+<br />
480482
<b>T</b> <b>+</b><i>tag-name</i> <b>*</b> ?<i>value</i>?<br />
481483
<b>U</b> <i>user-name</i><br />
482484
<b>W</b> <i>size</i> <b>\n</b> <i>text</i> <b>\n</b><br />
483485
<b>Z</b> <i>checksum</i>
484486
</blockquote>
485487
486488
The C card contains text that is displayed on the timeline for the
487
-event. The C card is optional, but there can only be one.
489
+technote. The C card is optional, but there can only be one.
488490
489491
A single D card is required to give the date and time when the
490
-event artifact was created. This is different from the time at which
491
-the event occurs.
492
+technote artifact was created. This is different from the time at which
493
+the technote appears on the timeline.
492494
493
-A single E card gives the time of the event (the point on the timeline
494
-where the event is displayed) and a unique identifier for the event.
495
-When there are multiple artifacts with the same event-id, the one with
496
-the most recent D card is the only one used. The event-id must be a
495
+A single E card gives the time of the technote (the point on the timeline
496
+where the technote is displayed) and a unique identifier for the technote.
497
+When there are multiple artifacts with the same technote-id, the one with
498
+the most recent D card is the only one used. The technote-id must be a
497499
40-character lower-case hexadecimal string.
498500
499
-The optional N card specifies the mimetype of the text of the event
501
+The optional N card specifies the mimetype of the text of the technote
500502
that is contained in the W card. If the N card is omitted, then the
501503
W card text mimetype is assumed to be text/x-fossil, which is the
502504
Fossil wiki format.
503505
504
-The optional P card specifies a prior event with the same event-id from
505
-which the current event is an edit. The P card is a hint to the system
506
-that it might be space efficient to store one event as a delta of the
507
-other.
506
+The optional P card specifies a prior technote with the same technote-id
507
+from which the current technote is an edit. The P card is a hint to the
508
+system that it might be space efficient to store one technote as a delta of
509
+the other.
508510
509
-An event might contain one or more T-cards used to set
511
+A technote might contain one or more T-cards used to set
510512
[./branching.wiki#tags | tags or properties]
511
-on the event. The format of the T-card is the same as
513
+on the technote. The format of the T-card is the same as
512514
described in [#ctrl | Control Artifacts] section above, except that the
513515
second argument is the single character "<b>*</b>" instead of an
514516
artifact ID and the name is always prefaced by "<b>+</b>".
515517
The <b>*</b> in place of the artifact ID indicates that
516518
the tag or property applies to the current artifact. It is not
517519
possible to encode the current artifact ID as part of an artifact,
518520
since the act of inserting the artifact ID would change the artifact ID,
519521
hence a <b>*</b> is used to represent "self". The "<b>+</b>" on the
520522
name means that tags can only be add and they can only be non-propagating
521
-tags. A an event, T cards are normally used to set the background
523
+tags. In a technote, T cards are normally used to set the background
522524
display color for timelines.
523525
524
-The optional U card gives name of the user who entered the event.
526
+The optional U card gives name of the user who entered the technote.
525527
526528
A single W card provides wiki text for the document associated with the
527
-event. The format of the W card is exactly the same as for a
529
+technote. The format of the W card is exactly the same as for a
528530
[#wikichng | wiki artifact].
529531
530532
The Z card is the required checksum over the rest of the artifact.
531533
532534
@@ -550,11 +552,11 @@
550552
<th>Cluster</th>
551553
<th>Control</th>
552554
<th>Wiki</th>
553555
<th>Ticket</th>
554556
<th>Attachment</th>
555
-<th>Event</th>
557
+<th>Technote</th>
556558
</tr>
557559
<tr>
558560
<td><b>A</b> <i>filename</i> <i>target</i> ?<i>source</i>?</td>
559561
<td>&nbsp;</td>
560562
<td>&nbsp;</td>
@@ -594,11 +596,11 @@
594596
<td align=center><b>1</b></td>
595597
<td align=center><b>1</b></td>
596598
<td align=center><b>1</b></td>
597599
</tr>
598600
<tr>
599
-<td><b>E</b> <i>event-time event-id</i></td>
601
+<td><b>E</b> <i>technote-time technote-id</i></td>
600602
<td>&nbsp;</td>
601603
<td>&nbsp;</td>
602604
<td>&nbsp;</td>
603605
<td>&nbsp;</td>
604606
<td>&nbsp;</td>
605607
--- www/fileformat.wiki
+++ www/fileformat.wiki
@@ -43,11 +43,11 @@
43 <li> [#cluster | Clusters] </li>
44 <li> [#ctrl | Control Artifacts] </li>
45 <li> [#wikichng | Wiki Pages] </li>
46 <li> [#tktchng | Ticket Changes] </li>
47 <li> [#attachment | Attachments] </li>
48 <li> [#event | Events] </li>
49 </ul>
50
51 These seven artifact types are described in the following sections.
52
53 In the current implementation (as of 2009-01-25) the artifacts that
@@ -423,11 +423,12 @@
423
424 <a name="attachment"></a>
425 <h2>6.0 Attachments</h2>
426
427 An attachment artifact associates some other artifact that is the
428 attachment (the source artifact) with a ticket or wiki page or event to which
 
429 the attachment is connected (the target artifact).
430 The following cards are allowed on an attachment artifact:
431
432 <blockquote>
433 <b>A</b> <i>filename target</i> ?<i>source</i>?<br />
@@ -437,12 +438,12 @@
437 <b>U</b> <i>user-name</i><br />
438 <b>Z</b> <i>checksum</i>
439 </blockquote>
440
441 The A card specifies a filename for the attachment in its first argument.
442 The second argument to the A card is the name
443 of the wiki page or ticket or event to which the attachment is connected. The
444 third argument is either missing or else it is the 40-character artifact
445 ID of the attachment itself. A missing third argument means that the
446 attachment should be deleted.
447
448 The C card is an optional comment describing what the attachment is about.
@@ -461,72 +462,73 @@
461 The Z card is the usual checksum over the rest of the attachment artifact.
462 The Z card is required.
463
464
465 <a name="event"></a>
466 <h2>7.0 Events</h2>
467
468 An event artifact associates a timeline comment and a page of text
469 (similar to a wiki page) with a point in time. Events can be used
 
470 to record project milestones, release notes, blog entries, process
471 checkpoints, or news articles.
472 The following cards are allowed on an event artifact:
473
474 <blockquote>
475 <b>C</b> <i>comment</i><br>
476 <b>D</b> <i>time-and-date-stamp</i><br />
477 <b>E</b> <i>event-time</i> <i>event-id</i><br />
478 <b>N</b> <i>mimetype</i><br />
479 <b>P</b> <i>parent-artifact-id</i>+<br />
480 <b>T</b> <b>+</b><i>tag-name</i> <b>*</b> ?<i>value</i>?<br />
481 <b>U</b> <i>user-name</i><br />
482 <b>W</b> <i>size</i> <b>\n</b> <i>text</i> <b>\n</b><br />
483 <b>Z</b> <i>checksum</i>
484 </blockquote>
485
486 The C card contains text that is displayed on the timeline for the
487 event. The C card is optional, but there can only be one.
488
489 A single D card is required to give the date and time when the
490 event artifact was created. This is different from the time at which
491 the event occurs.
492
493 A single E card gives the time of the event (the point on the timeline
494 where the event is displayed) and a unique identifier for the event.
495 When there are multiple artifacts with the same event-id, the one with
496 the most recent D card is the only one used. The event-id must be a
497 40-character lower-case hexadecimal string.
498
499 The optional N card specifies the mimetype of the text of the event
500 that is contained in the W card. If the N card is omitted, then the
501 W card text mimetype is assumed to be text/x-fossil, which is the
502 Fossil wiki format.
503
504 The optional P card specifies a prior event with the same event-id from
505 which the current event is an edit. The P card is a hint to the system
506 that it might be space efficient to store one event as a delta of the
507 other.
508
509 An event might contain one or more T-cards used to set
510 [./branching.wiki#tags | tags or properties]
511 on the event. The format of the T-card is the same as
512 described in [#ctrl | Control Artifacts] section above, except that the
513 second argument is the single character "<b>*</b>" instead of an
514 artifact ID and the name is always prefaced by "<b>+</b>".
515 The <b>*</b> in place of the artifact ID indicates that
516 the tag or property applies to the current artifact. It is not
517 possible to encode the current artifact ID as part of an artifact,
518 since the act of inserting the artifact ID would change the artifact ID,
519 hence a <b>*</b> is used to represent "self". The "<b>+</b>" on the
520 name means that tags can only be add and they can only be non-propagating
521 tags. A an event, T cards are normally used to set the background
522 display color for timelines.
523
524 The optional U card gives name of the user who entered the event.
525
526 A single W card provides wiki text for the document associated with the
527 event. The format of the W card is exactly the same as for a
528 [#wikichng | wiki artifact].
529
530 The Z card is the required checksum over the rest of the artifact.
531
532
@@ -550,11 +552,11 @@
550 <th>Cluster</th>
551 <th>Control</th>
552 <th>Wiki</th>
553 <th>Ticket</th>
554 <th>Attachment</th>
555 <th>Event</th>
556 </tr>
557 <tr>
558 <td><b>A</b> <i>filename</i> <i>target</i> ?<i>source</i>?</td>
559 <td>&nbsp;</td>
560 <td>&nbsp;</td>
@@ -594,11 +596,11 @@
594 <td align=center><b>1</b></td>
595 <td align=center><b>1</b></td>
596 <td align=center><b>1</b></td>
597 </tr>
598 <tr>
599 <td><b>E</b> <i>event-time event-id</i></td>
600 <td>&nbsp;</td>
601 <td>&nbsp;</td>
602 <td>&nbsp;</td>
603 <td>&nbsp;</td>
604 <td>&nbsp;</td>
605
--- www/fileformat.wiki
+++ www/fileformat.wiki
@@ -43,11 +43,11 @@
43 <li> [#cluster | Clusters] </li>
44 <li> [#ctrl | Control Artifacts] </li>
45 <li> [#wikichng | Wiki Pages] </li>
46 <li> [#tktchng | Ticket Changes] </li>
47 <li> [#attachment | Attachments] </li>
48 <li> [#event | TechNotes] </li>
49 </ul>
50
51 These seven artifact types are described in the following sections.
52
53 In the current implementation (as of 2009-01-25) the artifacts that
@@ -423,11 +423,12 @@
423
424 <a name="attachment"></a>
425 <h2>6.0 Attachments</h2>
426
427 An attachment artifact associates some other artifact that is the
428 attachment (the source artifact) with a ticket or wiki page or
429 technical note to which
430 the attachment is connected (the target artifact).
431 The following cards are allowed on an attachment artifact:
432
433 <blockquote>
434 <b>A</b> <i>filename target</i> ?<i>source</i>?<br />
@@ -437,12 +438,12 @@
438 <b>U</b> <i>user-name</i><br />
439 <b>Z</b> <i>checksum</i>
440 </blockquote>
441
442 The A card specifies a filename for the attachment in its first argument.
443 The second argument to the A card is the name of the wiki page or
444 ticket or technical note to which the attachment is connected. The
445 third argument is either missing or else it is the 40-character artifact
446 ID of the attachment itself. A missing third argument means that the
447 attachment should be deleted.
448
449 The C card is an optional comment describing what the attachment is about.
@@ -461,72 +462,73 @@
462 The Z card is the usual checksum over the rest of the attachment artifact.
463 The Z card is required.
464
465
466 <a name="event"></a>
467 <h2>7.0 Technical Notes</h2>
468
469 A technical note or "technote" artifact (formerly known as an "event" artifact)
470 associates a timeline comment and a page of text
471 (similar to a wiki page) with a point in time. Technotes can be used
472 to record project milestones, release notes, blog entries, process
473 checkpoints, or news articles.
474 The following cards are allowed on an technote artifact:
475
476 <blockquote>
477 <b>C</b> <i>comment</i><br>
478 <b>D</b> <i>time-and-date-stamp</i><br />
479 <b>E</b> <i>technote-time</i> <i>technote-id</i><br />
480 <b>N</b> <i>mimetype</i><br />
481 <b>P</b> <i>parent-artifact-id</i>+<br />
482 <b>T</b> <b>+</b><i>tag-name</i> <b>*</b> ?<i>value</i>?<br />
483 <b>U</b> <i>user-name</i><br />
484 <b>W</b> <i>size</i> <b>\n</b> <i>text</i> <b>\n</b><br />
485 <b>Z</b> <i>checksum</i>
486 </blockquote>
487
488 The C card contains text that is displayed on the timeline for the
489 technote. The C card is optional, but there can only be one.
490
491 A single D card is required to give the date and time when the
492 technote artifact was created. This is different from the time at which
493 the technote appears on the timeline.
494
495 A single E card gives the time of the technote (the point on the timeline
496 where the technote is displayed) and a unique identifier for the technote.
497 When there are multiple artifacts with the same technote-id, the one with
498 the most recent D card is the only one used. The technote-id must be a
499 40-character lower-case hexadecimal string.
500
501 The optional N card specifies the mimetype of the text of the technote
502 that is contained in the W card. If the N card is omitted, then the
503 W card text mimetype is assumed to be text/x-fossil, which is the
504 Fossil wiki format.
505
506 The optional P card specifies a prior technote with the same technote-id
507 from which the current technote is an edit. The P card is a hint to the
508 system that it might be space efficient to store one technote as a delta of
509 the other.
510
511 A technote might contain one or more T-cards used to set
512 [./branching.wiki#tags | tags or properties]
513 on the technote. The format of the T-card is the same as
514 described in [#ctrl | Control Artifacts] section above, except that the
515 second argument is the single character "<b>*</b>" instead of an
516 artifact ID and the name is always prefaced by "<b>+</b>".
517 The <b>*</b> in place of the artifact ID indicates that
518 the tag or property applies to the current artifact. It is not
519 possible to encode the current artifact ID as part of an artifact,
520 since the act of inserting the artifact ID would change the artifact ID,
521 hence a <b>*</b> is used to represent "self". The "<b>+</b>" on the
522 name means that tags can only be add and they can only be non-propagating
523 tags. In a technote, T cards are normally used to set the background
524 display color for timelines.
525
526 The optional U card gives name of the user who entered the technote.
527
528 A single W card provides wiki text for the document associated with the
529 technote. The format of the W card is exactly the same as for a
530 [#wikichng | wiki artifact].
531
532 The Z card is the required checksum over the rest of the artifact.
533
534
@@ -550,11 +552,11 @@
552 <th>Cluster</th>
553 <th>Control</th>
554 <th>Wiki</th>
555 <th>Ticket</th>
556 <th>Attachment</th>
557 <th>Technote</th>
558 </tr>
559 <tr>
560 <td><b>A</b> <i>filename</i> <i>target</i> ?<i>source</i>?</td>
561 <td>&nbsp;</td>
562 <td>&nbsp;</td>
@@ -594,11 +596,11 @@
596 <td align=center><b>1</b></td>
597 <td align=center><b>1</b></td>
598 <td align=center><b>1</b></td>
599 </tr>
600 <tr>
601 <td><b>E</b> <i>technote-time technote-id</i></td>
602 <td>&nbsp;</td>
603 <td>&nbsp;</td>
604 <td>&nbsp;</td>
605 <td>&nbsp;</td>
606 <td>&nbsp;</td>
607

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button