Fossil

Changes On Branch wcontent-subsets
Login

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

Changes In Branch wcontent-subsets Excluding Merge-Ins

This is equivalent to a diff from a004b1729c to 282c6f956f

2021-08-17
15:41
Improvements to the /urllist page → the sync URLs and Git mirrors are combined into a single section. Add the url_unparse() interface for freeing memory from a url_parse_local(). ... (check-in: 9bdbcd39cb user: drh tags: trunk)
2021-08-16
00:11
Relax <tt>isSnippetMark()</tt> so that almost arbitrary search terms are highlighted. This change is preliminary and [forum:/forumpost/042e179e0c25b8|needs further analysis]. ... (Leaf check-in: 6b37b55f75 user: george tags: search-terms-highlighting)
2021-08-15
23:49
Merge from trunk ... (Leaf check-in: 59010c7c09 user: george tags: rptview-submenu-paralink)
23:27
Merge from trunk ... (Leaf check-in: 282c6f956f user: george tags: wcontent-subsets)
23:13
Merge from trunk ... (Leaf check-in: 5b67899db0 user: george tags: th1-doc-vars)
18:38
Remove a harmless unused variable. ... (check-in: a004b1729c user: drh tags: trunk)
00:43
Improve the /urllist page so that it shows all servers with which the repository has synced. ... (check-in: 89e5c03a32 user: drh tags: trunk)
2021-06-15
21:37
Merge from trunk ... (check-in: cea36e6c86 user: george tags: wcontent-subsets)

Changes to src/db.c.
4307
4308
4309
4310
4311
4312
4313








































4314
4315
4316
4317
4318
4319
4320
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







/*
** SETTING: web-browser      width=30 sensitive
** A shell command used to launch your preferred
** web browser when given a URL as an argument.
** Defaults to "start" on windows, "open" on Mac,
** and "firefox" on Unix.
*/
/*
** SETTING: wiki-classes     width=40 block-text
** Defines classes for wiki pages that are recognized by the list
** of available wiki pages (displayed by /wcontent web page).
**
** Each line defines a single rule for a class using a triplet:
** Visibility   Label   Pattern
**
** Visibility is one of the following letters:
**
**     s  show on load, may be toggled afterwards
**     h  hide on load, may be toggled afterwards
**     d  hide permanently, checkbox disabled
**     x  exclude completely, no control in the submenu
**
** Label is a spaces-free name of the class shown in the submenu.
** This very same string is used as a value for HTML's class=""
** atributes on the corresponding rows (thus beware of mangling).
**
** Pattern is a GLOB pattern against which wiki page names are
** matched to distinguish a class. Case-sensitive pattern matching
** is performed if the Visibility is specified by a lowercase letter,
** otherwise pattern matching is case-insensitive (in which case
** the syntax of SQLite's LIKE operator applies).
** Pattern that consists of just a single * is a special case for
** catching all wiki pages that do not fall into any other class
** (this fallback does not depend on the case of the Visibility letter).
**
** If several consequtive lines share the same Label then this defines
** a single class that spans accross several patterns. In that case
** all Visibilities must also be equal (modulus upper/lower cases).
**
** Patterns are matched in the order of their appearance in the list.
** If a repository manages thousands of wiki pages and the /wcontent
** page is requested very frequently then server's CPU load may become
** a concern. In that case an administrator is advised to rearrange
** classes in the list in such a way that more patterns are matched
** earlier. In all cases it is advised to keep a special "catch-all"
** class in the bottom of the list.
*/

/*
** Look up a control setting by its name.  Return a pointer to the Setting
** object, or NULL if there is no such setting.
**
** If allowPrefix is true, then the Setting returned is the first one for
** which zName is a prefix of the Setting name.
Added src/fossil.page.wcontent.js.
















































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/* This script implements interactivity of checkboxes that
 * toggle visibilitiy of user-defined classes of wikipage.
 *
 * For the sake of compatibility with ascetic browsers the code tries
 * to avoid modern API and ECMAScript constructs. This makes it less
 * readable and may be reconsidered in the future.
*/
window.addEventListener( 'load', function() {

var tbody = document.querySelector(
            "body.wiki div.content table.sortable > tbody");
var prc = document.getElementById("page-reload-canary");
if( !tbody || !prc ) return;

var reloading = prc.checked;
// console.log("Reloading:",reloading);

var onChange = function(event){
  var display = event.target.checked ? "" : "none";
  var rows    = event.target.matchingRows;
  for(var i=0; i<rows.length; i++)
    rows[i].style.display = display;
}
var checkboxes = [];
document.querySelectorAll(
  "body.wiki .submenu > label.submenuckbox > input")
  .forEach(function(cbx){ checkboxes.push(cbx); });

for(var j=0; j<checkboxes.length; j++){
  var cbx = checkboxes[j];
  var ctrl = cbx.getAttribute("data-ctrl").toString();
  var cname = cbx.parentElement.innerText.toString();
  var hidden = ( ctrl == 'h' || ctrl == 'd' );
  if( reloading )
    hidden = !cbx.checked;
  else
    cbx.checked = !hidden;
  cbx.matchingRows = [];
  tbody.querySelectorAll("tr."+cname).forEach(function (tr){
    tr.style.display = ( hidden ? "none" : "" );
    cbx.matchingRows.push(tr);
  });
  cbx.addEventListener("change", onChange ); 
  // console.log( cbx.matchingRows.length, cname, ctrl );
}

prc.checked = true;
}); // window.addEventListener( 'load' ...
Changes to src/main.mk.
229
230
231
232
233
234
235

236
237
238
239
240
241
242
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243







+







  $(SRCDIR)/fossil.fetch.js \
  $(SRCDIR)/fossil.info-diff.js \
  $(SRCDIR)/fossil.numbered-lines.js \
  $(SRCDIR)/fossil.page.brlist.js \
  $(SRCDIR)/fossil.page.fileedit.js \
  $(SRCDIR)/fossil.page.forumpost.js \
  $(SRCDIR)/fossil.page.pikchrshow.js \
  $(SRCDIR)/fossil.page.wcontent.js \
  $(SRCDIR)/fossil.page.whistory.js \
  $(SRCDIR)/fossil.page.wikiedit.js \
  $(SRCDIR)/fossil.pikchr.js \
  $(SRCDIR)/fossil.popupwidget.js \
  $(SRCDIR)/fossil.storage.js \
  $(SRCDIR)/fossil.tabs.js \
  $(SRCDIR)/fossil.wikiedit-wysiwyg.js \
Changes to src/wiki.c.
19
20
21
22
23
24
25


















26
27
28
29
30
31
32
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







** This file contains code to do formatting of wiki text.
*/
#include "config.h"
#include <assert.h>
#include <ctype.h>
#include "wiki.h"

#if INTERFACE

/*
** WikiClass struct holds information for matching a wiki page name.
** It is constructed by load_wiki_classes() function and represents a
** single well-formed line obtained from the 'wiki-classes' setting.
*/
struct WikiClass {
  const char * zPattern; /* pattern to match against                    */
  int   isCaseIns;       /* syntax flag: 0 for GLOB, 1 for LIKE         */
  short isAltPat;        /* indicates an additional pattern for a class */

  const char * zVisblty; /* visibility flag, one of: "s" "h" "d" "x"    */
  const char * zLabel;   /* user-visible class name, same in HTML attrs */
  const char * zParam;   /* checkbox attr, like in <input name="..." /> */
};
#endif

/*
** Return true if the input string is a well-formed wiki page name.
**
** Well-formed wiki page names do not begin or end with whitespace,
** and do not contain tabs or other control characters and do not
** contain more than a single space character in a row.  Well-formed
** names must be between 1 and 100 characters in length, inclusive.
437
438
439
440
441
442
443




















































































































444
445
446
447
448
449
450
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    case WIKITYPE_CHECKIN: return "checkin";
    case WIKITYPE_BRANCH: return "branch";
    case WIKITYPE_TAG: return "tag";
    case WIKITYPE_NORMAL:
    default: return "normal";
  }
}

/*
** load_wiki_classes() loads and parses the value of the 'wiki-classes'
** setting. Retrurns either NULL or a dynamically allocated array of
** WikiClasses (thus fossil_free() for the returned value is advised).
*/
WikiClass* load_wiki_classes(
  int *nWC,  /* number of well-formed elements in the returned array    */
  Blob *wcs  /* holds a buffer for strings in the returned WikiClass'es */
){

  static const char *zPN[] = { /* no malloc() for the common cases */
     "wc0", "wc1", "wc2", "wc3", "wc4", "wc5", "wc6", "wc7",
     "wc8", "wc9","wc10","wc11","wc12","wc13","wc14","wc15",
    "wc16","wc17","wc18","wc19","wc20","wc21","wc22","wc23"
  };
  WikiClass* aWC = 0;
  int n = 0;
  char *zWCS = db_get("wiki-classes",0);
  if( zWCS && strlen(zWCS) >= 5 ){
    Blob line  = empty_blob;
    int nAlloc = 0;
    blob_set_dynamic(wcs,zWCS);
    while( blob_line(wcs,&line) > 0 ){
      Blob vis = empty_blob;
      Blob lbl = empty_blob;
      Blob pat = empty_blob;
      WikiClass * wc;
      const char *z;
      int cins = 0;
      char v;
      if( blob_token(&line,&vis) != 1 ){
        continue;
      }
      v = vis.aData[0];
      switch( v ){
        case 'D':
        case 'H':
        case 'S':
        case 'X':
          cins = 1;
          vis.aData[0] = (char)tolower(v);
        case 'd':
        case 'h':
        case 's':
        case 'x':
          break;
        default:
          v = 0;
      }
      if( v == 0 ) continue;
      if( blob_token(&line,&lbl) <= 0 ){
        continue;
      }
      blob_tail(&line,&pat);
      /* blob_to_lf_only(&pre); <-- this is redundant, isn't it ? */
      blob_trim(&pat);
      z = blob_terminate(&pat);
      while(fossil_isspace(z[0])) z++;
      if( z[0] == 0 ){
        continue;
      }
      if( n >= nAlloc ){
        nAlloc += count(zPN);
        aWC = (WikiClass*)( aWC ?
             fossil_realloc(aWC,sizeof(WikiClass)*nAlloc)  :
             fossil_malloc_zero(sizeof(WikiClass)*nAlloc) );
      }
      wc = aWC + n;
      wc->zPattern  = z;
      wc->isCaseIns = cins;
      wc->zVisblty  = blob_terminate(&vis);
      wc->zLabel    = blob_terminate(&lbl);
      wc->zParam    = ( n < count(zPN) ? zPN[n] : mprintf("wc%d",n) );
      if( n > 0 && strcmp( wc->zLabel, wc[-1].zLabel ) == 0 ){
        if( wc->zVisblty[0] != wc[-1].zVisblty[0] ||
            strcmp( wc->zPattern, wc[-1].zPattern ) == 0 ){
          continue;
        }
        wc->isAltPat = 1;
      }else{
        wc->isAltPat = 0;
      }
      n++;
    }
  }
  if( nWC ) *nWC = n;
  return aWC;
}
/*
** Find and return a WikiClass that matches a name of a wiki page.
** Returns 0 if "fallback" pattern was not provisioned.
*/
const WikiClass* resolve_wiki_class(
  const char *zName,    /* name of a wiki page that should be classified */
  const WikiClass *aWC, /* pointer to the array of WikiClass'es          */
  int nWC               /* number of elements in the above array         */
){
  const WikiClass* fallback = 0;
  if( aWC && zName ){
    int i;
    for( i=0; i<nWC; i++ ){
      const WikiClass* wc = aWC + i;
      if( wc->zPattern[0] == '*' && wc->zPattern[1] == 0 ){
        if( !fallback ) fallback = wc;
      }else if( wc->isCaseIns ){
        if( sqlite3_strlike( wc->zPattern, zName, 0 ) == 0 )
          return wc;
      }else{
        if( sqlite3_strglob( wc->zPattern, zName ) == 0 )
          return wc;
      }
    }
  }
  return fallback;
}

/*
** Add an appropriate style_header() for either the /wiki or /wikiedit page
** for zPageName.  zExtra is an empty string for /wiki but has the text
** "Edit: " for /wikiedit.
**
** If the page is /wiki and the page is one of the special times (check-in,
1904
1905
1906
1907
1908
1909
1910



1911
1912
1913
1914
1915
1916
1917
1918
1919
1920







1921
1922

1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942



1943
1944



1945
1946
1947

1948

1949
1950





1951

1952
1953





1954

1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968

1969
1970


1971
1972
1973
1974
1975
1976
1977
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090


2091
2092
2093
2094
2095

2096
2097
2098
2099
2100
2101
2102
2103
2104
2105

2106
2107
2108
2109
2110
2111
2112
2113

2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140







+
+
+










+
+
+
+
+
+
+


+




















+
+
+
-
-
+
+
+


-
+

+


+
+
+
+
+
-
+


+
+
+
+
+
-
+














+


+
+







** List all available wiki pages with date created and last modified.
*/
void wcontent_page(void){
  Stmt q;
  double rNow;
  int showAll = P("all")!=0;
  int showRid = P("showid")!=0;
  Blob wcs = empty_blob;
  int i, nWC = 0;
  WikiClass* aWC;

  login_check_credentials();
  if( !g.perm.RdWiki ){ login_needed(g.anon.RdWiki); return; }
  style_set_current_feature("wiki");
  style_header("Available Wiki Pages");
  if( showAll ){
    style_submenu_element("Active", "%R/wcontent");
  }else{
    style_submenu_element("All", "%R/wcontent?all=1");
  }
  aWC = load_wiki_classes(&nWC,&wcs);
  for( i=0; i<nWC; i++ ){
    const WikiClass * c = aWC + i;
    if( c->isAltPat || c->zVisblty[0] == 'x' ) continue;
    style_submenu_checkbox( c->zParam, c->zLabel,
      c->zVisblty[0]=='d' ? STYLE_DISABLED : STYLE_NORMAL, c->zVisblty);
  }
  wiki_standard_submenu(W_ALL_BUT(W_LIST));
  db_prepare(&q, listAllWikiPages/*works-like:""*/);
  @ <input hidden="hidden" id="page-reload-canary" type="checkbox"/>
  @ <div class="brlist">
  @ <table class='sortable' data-column-types='tKN' data-init-sort='1'>
  @ <thead><tr>
  @ <th>Name</th>
  @ <th>Last Change</th>
  @ <th>Versions</th>
  if( showRid ){
    @ <th>RID</th>
  }
  @ </tr></thead><tbody>
  rNow = db_double(0.0, "SELECT julianday('now')");
  while( db_step(&q)==SQLITE_ROW ){
    const char *zWName = db_column_text(&q, 0);
    const char *zSort = db_column_text(&q, 1);
    int wrid = db_column_int(&q, 2);
    double rWmtime = db_column_double(&q, 3);
    sqlite3_int64 iMtime = (sqlite3_int64)(rWmtime*86400.0);
    char *zAge;
    int wcnt = db_column_int(&q, 4);
    char *zWDisplayName;
    const WikiClass * wc = resolve_wiki_class(zWName,aWC,nWC);
    if( wc && (wc->zVisblty[0] == 'x' || wc->zVisblty[0] == 'd') ){
      continue;

    if( sqlite3_strglob("checkin/*", zWName)==0 ){
    }

    if( sqlite3_strglob("checkin/*", zWName)==0 ){ /* --?--> strncmp() */
      zWDisplayName = mprintf("%.25s...", zWName);
    }else{
      zWDisplayName = mprintf("%s", zWName);
      zWDisplayName = mprintf("%s", zWName); /* --?--> fossil_strdup() */
    }

    if( wrid==0 ){
      if( !showAll ) continue;
      if(wc){
        @ <tr class="%h(wc->zLabel)">
      }else{
        @ <tr>
      }
      @ <tr><td data-sortkey="%h(zSort)">\
      @ <td data-sortkey="%h(zSort)">\
      @ %z(href("%R/whistory?name=%T",zWName))<s>%h(zWDisplayName)</s></a></td>
    }else{
      if(wc){
        @ <tr class="%h(wc->zLabel)">
      }else{
        @ <tr>
      }
      @ <tr><td data-sortkey="%h(zSort)">\
      @ <td data-sortkey="%h(zSort)">\
      @ %z(href("%R/wiki?name=%T&p",zWName))%h(zWDisplayName)</a></td>
    }
    zAge = human_readable_age(rNow - rWmtime);
    @ <td data-sortkey="%016llx(iMtime)">%s(zAge)</td>
    fossil_free(zAge);
    @ <td>%z(href("%R/whistory?name=%T",zWName))%d(wcnt)</a></td>
    if( showRid ){
      @ <td>%d(wrid)</td>
    }
    @ </tr>
    fossil_free(zWDisplayName);
  }
  @ </tbody></table></div>
  db_finalize(&q);
  builtin_request_js("fossil.page.wcontent.js");
  style_table_sorter();
  style_finish_page();
  if(aWC) fossil_free(aWC);
  blob_reset(&wcs); /* FIXME: it's an analog of fossil_free(), isn't it? */
}

/*
** WEBPAGE: wfind
**
** URL: /wfind?title=TITLE
** List all wiki pages whose titles contain the search text
Changes to www/changes.wiki.
21
22
23
24
25
26
27






28
29
30
31
32
33
34
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40







+
+
+
+
+
+







  *  Print total payload bytes on a [/help?cmd=sync|fossil sync] when using
     the --verbose option.
  *  Add the <tt>close</tt>, <tt>reopen</tt>, <tt>hide</tt>, and
     </tt>unhide</tt> subcommands to [/help?cmd=branch|the branch command].
  *  The [/mdrules|Markdown formatter] now interprets the content of
     block HTML markup (such as &lt;table&gt;) in most cases.  Only content
     of &lt;pre&gt; and &lt;script&gt; is passed through verbatim.
  *  [/wcontent|Listing] of the available wiki pages
     [/timeline?r=wcontent-subsets|gained] the ability to
     [./javascript.md#wcontent|interactively] adjust a subset of
     wiki pages that are shown; this is based on the
     classification of wiki page names according to the
     [/help?cmd=wiki-classes|configurable] glob patterns.

<a name='v2_16'></a>
<h2>Changes for Version 2.16 (2021-07-02)</h2>
  *  <b>Security:</b> Fix the client-side TLS so that it verifies that the
     server hostname matches its certificate.
  *  The default "ssh" command on Windows is changed to "ssh" instead of the
     legacy "plink", as ssh is now generally available on Windows systems.
325
326
327
328
329
330
331
332

333
334
335
336
337
338
339
331
332
333
334
335
336
337

338
339
340
341
342
343
344
345







-
+







  *  Added virtual tables "<tt>helptext</tt>" and "<tt>builtin</tt>" to
     the "[/help?cmd=sql|fossil sql]" command, providing access to the
     dispatch table including all help text, and the builtin data files,
     respectively.
  *  [./delta_format.wiki|Delta compression] is now applied to forum edits.
  *  The [/help?cmd=/wikiedit|wiki editor] has been modernized and is
     now Ajax-based. The WYSIWYG editing option for Fossil-format wiki
     pages was removed. (Please let us know, via the site's Forum menu,
     pages was removed. (Please let us know, via the site's Support menu,
     if that removal unduly impacts you.) This also changes the semantics
     of the wiki "Sandbox": that pseudo-page may be freely edited but
     no longer saved via the UI (the [/help?cmd=wiki|wiki CLI command]
     can, though).
  *  The [/help?cmd=allow-symlinks|allow-symlinks setting] no longer
     syncs. It must be activated individually on any clones which require
     symlinks.
Changes to www/javascript.md.
581
582
583
584
585
586
587









588
589
590
591
592
593
594
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603







+
+
+
+
+
+
+
+
+







Clicking this hyperlink loads a `/timeline` page that shows
only these selected branches (and the related check-ins).

_Potential Workaround:_ A user can manually construct an appropriate
regular expession and put it into the "Tag Filter" entry of the
`/timeline` page (in its advanced mode).

### <a id="wcontent"></a>Wiki content listing

[Since](/timeline?r=wcontent-subsets) version 2.16 it is possible to
add [configurable](/help?cmd=wiki-classes) checkbox controls to the
submenu of [available wiki pages](/wcontent) for the interactive
adjustment of a subset of wiki pages that are shown.
Client-side script is used to toggle visibility of the corresponding
rows according to the state of these checkboxes.

----

## <a id="future"></a>Future Plans for JavaScript in Fossil

As of mid-2020, the informal provisional plan is to increase Fossil
UI's use of JavaScript considerably compared to its historically minimal
uses. To that end, a framework of Fossil-centric APIs is being developed