Documentation Source Text

Check-in [368f8fa51f]
Login

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

Overview
Comment:Add a website option to search the changelog instead of the documentation. Do not add any changelog files to the documentation index.
Timelines: family | ancestors | descendants | both | changelog-search
Files: files | file ages | folders
SHA3-256: 368f8fa51fdf51c2b99bcd57b230f7dd73ece512cd442591f31d410c6d218e6c
User & Date: dan 2017-08-01 19:24:32
Context
2017-08-01
19:29
Add a website option to search the changelog instead of the documentation. Do not add any changelog files to the documentation index. check-in: 8f15082015 user: dan tags: trunk
19:24
Add a website option to search the changelog instead of the documentation. Do not add any changelog files to the documentation index. Closed-Leaf check-in: 368f8fa51f user: dan tags: changelog-search
18:42
Fix a typo in the changelog for release 3.4.0. check-in: 0a8c13265d user: dan tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to document_header.tcl.

    34     34             <li class='wideonly'><a href='${path}about.html'>About</a>
    35     35             <li class='desktoponly'><a href="${path}docs.html">Documentation</a>
    36     36             <li class='desktoponly'><a href="${path}download.html">Download</a>
    37     37             <li class='wideonly'><a href='${path}copyright.html'>License</a>
    38     38             <li class='desktoponly'><a href="${path}support.html">Support</a>
    39     39             <li class='desktoponly'><a href="${path}prosupport.html">Purchase</a>
    40     40             <li class='search' id='search_menubutton'>
    41         -            <a href="javascript:void(0)" onclick='toggle_div("searchmenu")'>Search</a>
           41  +            <a href="javascript:void(0)" onclick='toggle_search()'>Search</a>
    42     42           </ul>
    43     43         </div>
    44     44         <div class="menu submenu" id="submenu">
    45     45           <ul>
    46     46             <li><a href='${path}about.html'>About</a>
    47     47             <li><a href='${path}docs.html'>Documentation</a>
    48     48             <li><a href='${path}download.html'>Download</a>
    49     49             <li><a href='${path}support.html'>Support</a>
    50     50             <li><a href='${path}prosupport.html'>Purchase</a>
    51     51           </ul>
    52     52         </div>
    53     53         <div class="searchmenu" id="searchmenu">
    54     54           <form method="GET" action="${path}search">
    55         -          <span class="desktoponly">Search for:</span> <input type="text" name="q">
           55  +          <select name="s" id="searchtype">
           56  +            <option value="d">Search Documentation</option>
           57  +            <option value="c">Search Changelog</option>
           58  +          </select>
           59  +          <input type="text" name="q" id="searchbox" value="$search">
    56     60             <input type="submit" value="Go">
    57     61           </form>
    58     62         </div>
    59     63       </div>
    60     64     }]
    61     65   
    62     66     append ret [subst -nocommands {
................................................................................
    65     69           var w = document.getElementById(nm);
    66     70           if( w.style.display=="block" ){
    67     71             w.style.display = "none";
    68     72           }else{
    69     73             w.style.display = "block";
    70     74           }
    71     75         }
           76  +
           77  +      function toggle_search() {
           78  +        var w = document.getElementById("searchmenu");
           79  +        if( w.style.display=="block" ){
           80  +          w.style.display = "none";
           81  +        } else {
           82  +          w.style.display = "block";
           83  +          setTimeout(function(){
           84  +            document.getElementById("searchbox").focus()
           85  +          }, 30);
           86  +        }
           87  +      }
           88  +
    72     89         function div_off(nm){document.getElementById(nm).style.display="none";}
    73     90         window.onbeforeunload = function(e){div_off("submenu");}
    74     91   
    75     92         /* Disable the Search feature if we are not operating from CGI, since */
    76     93         /* Search is accomplished using CGI and will not work without it. */
    77     94         if( !location.origin.match || !location.origin.match(/http/) ){
    78     95           document.getElementById("search_menubutton").style.display = "none";

Changes to search/buildsearchdb.tcl.

     2      2   
     3      3   #load ./parsehtml.so
     4      4   #load ./tokenize.so
     5      5   
     6      6   source [file join [file dirname [info script]] hdom.tcl]
     7      7   
     8      8   set ::G(rowid) 1
            9  +
           10  +proc releaselog_to_version {doc} {
           11  +  set version 0_0_0
           12  +  regexp {releaselog/(.*).html} $doc -> version
           13  +  split $version _
           14  +}
           15  +
           16  +proc release_cmp {a b} {
           17  +  set v1 [releaselog_to_version $a]
           18  +  set v2 [releaselog_to_version $b]
           19  +  lappend v1 {*}[lrange {-1 -1 -1 -1 -1} [llength $v1] end]
           20  +  lappend v2 {*}[lrange {-1 -1 -1 -1 -1} [llength $v2] end]
           21  +  foreach x $v1 y $v2 {
           22  +    if {$x < $y} { return -1 }
           23  +    if {$x > $y} { return +1 }
           24  +  }
           25  +  return 0
           26  +}
     9     27   
    10     28   # Return a list of relative paths to documents that should be included 
    11     29   # in the index.
    12     30   proc document_list {type} {
    13     31     global weight
    14     32     set lFiles [list]
    15     33     switch -- $type {
................................................................................
    79     97            || [regexp {^(3_9_).*} $tail -> prefix]
    80     98            || [regexp {^(3_[1-9][0-9]).*} $tail -> prefix]
    81     99           } {
    82    100             set f1 [lindex [lsort -decreasing [glob releaselog/$prefix*.html]] 0]
    83    101             if {$f!=$f1} { set ::weight($f) 10 }
    84    102           } 
    85    103         }
          104  +    }
    86    105   
    87         -      foreach f [glob releaselog/*.html] { 
    88         -        if {[info exists nosearch($f)]==0} { 
    89         -          lappend lFiles $f 
    90         -        }
          106  +    changelog {
          107  +      foreach f [lsort -decr -command release_cmp [glob releaselog/*.html]] { 
          108  +        if {$f != "releaselog/current.html"} { lappend lFiles $f }
    91    109         }
    92    110       }
    93    111   
    94    112       default {
    95    113         error "document_list: unknown file type $type"
    96    114       }
    97    115     }
................................................................................
   218    236   
   219    237   proc generic_filterscript {N} {
   220    238     for {set P [$N parent]} {$P!=""} {set P [$P parent]} {
   221    239       if {[$P attr -default "" class]=="nosearch"} { return 0 }
   222    240     }
   223    241     return 1
   224    242   }
          243  +
          244  +proc releaselog_filterscript {N} {
          245  +  for {set P [$N parent]} {$P!=""} {set P [$P parent]} {
          246  +    if {[$P attr -default "" class]=="nosearch"} { return 0 }
          247  +    if {[$P tag]=="li"} { return 0 }
          248  +  }
          249  +  return 1
          250  +}
   225    251   
   226    252   proc extract_text_from_dom {dom filterscript} {
   227    253     set text ""
   228    254     set body [lindex [[$dom root] search body] 0]
   229    255     $body foreach_descendent N {
   230    256       if {[$N tag]==""} {
   231    257         if {[eval $filterscript $N]} { append text [$N text] }
................................................................................
   333    359       foreach { tag hdr text } $section {}
   334    360       if {[string trim $text]==""} continue
   335    361       incr i
   336    362       set url "${doc}#${tag}"
   337    363       insert_entry -rowid $i -url $url -title1 $title -title2 $hdr -content $text
   338    364     }
   339    365   }
          366  +
          367  +proc changelog_document_import {doc} {
          368  +
          369  +  set content [readfile $doc]
          370  +  set end [string first "Changes carried forward from version " $content]
          371  +  if {$end>0} { set content [string range $content 0 $end] }
          372  +
          373  +  set dom [::hdom::parse $content]
          374  +
          375  +  # Extract the version number from the document name.
          376  +  set version 0.0.0
          377  +  regexp {releaselog/(.*).html} $doc -> version
          378  +  set version [string map {_ .} $version]
          379  +
          380  +  # Find each of the <li> nodes in the document.
          381  +  foreach li [[$dom root] search li] {
          382  +    if {0==[releaselog_filterscript $li]} continue
          383  +
          384  +    set i 1
          385  +    set ol [$li parent]
          386  +    if {$ol=="" || [$ol tag]!="ol"} {error UNTHINKABLE!}
          387  +    foreach c [$ol children] {
          388  +      if {$c==$li} break
          389  +      if {[$c tag]=="li"} {incr i}
          390  +    }
          391  +
          392  +    set t [$li text]
          393  +    db eval { INSERT INTO change VALUES($doc, $version, $i, $t) }
          394  +  }
          395  +}
   340    396   
   341    397   proc rebuild_database {} {
   342    398   
   343    399     db transaction {
   344    400       # Create the database schema. If the schema already exists, then those
   345    401       # tables that contain document data are dropped and recreated by this
   346    402       # proc. The 'config' table is left untouched.
................................................................................
   358    414           tokenize='stoken unicode61 tokenchars _' -- Tokenizer definition
   359    415         );
   360    416   
   361    417         DROP TABLE IF EXISTS weight;
   362    418         CREATE TABLE weight(id INTEGER PRIMARY KEY, percent FLOAT);
   363    419   
   364    420         INSERT INTO page(page, rank) VALUES('rank', 'bm25(10.0,10.0,20.0,20.0)');
          421  +
          422  +      DROP TABLE IF EXISTS change;
          423  +      CREATE VIRTUAL TABLE change USING fts5(
          424  +          url UNINDEXED,          -- Path to document
          425  +          version UNINDEXED,      -- SQLite version number
          426  +          idx UNINDEXED,          -- Bullet point number
          427  +          text                    -- Text of change log entry
          428  +      );
          429  +    }
          430  +
          431  +    foreach doc [document_list changelog] { 
          432  +      puts "Indexing $doc..."
          433  +      changelog_document_import $doc 
   365    434       }
   366    435   
   367    436       foreach doc [document_list lang] {
   368    437         puts "Indexing $doc..."
   369    438         lang_document_import $doc
   370    439       }
   371    440   
................................................................................
   374    443         c3ref_document_import $doc
   375    444       }
   376    445   
   377    446       foreach doc [document_list generic] { 
   378    447         puts "Indexing $doc..."
   379    448         generic_document_import $doc 
   380    449       }
          450  +
   381    451   
   382    452       db eval { INSERT INTO page(page) VALUES('optimize') }
          453  +    db eval { INSERT INTO change(change) VALUES('optimize') }
   383    454   
   384    455       foreach f [array names ::weight] {
   385    456         set w $::weight($f)
   386    457         db eval {SELECT rowid FROM page WHERE url=$f} {
   387    458           db eval { INSERT INTO weight VALUES($rowid, $w); }
   388    459         }
   389    460       }

Changes to search/search.tcl.

   113    113       BEGIN;
   114    114         CREATE TABLE IF NOT EXISTS log(
   115    115           ip,                  -- IP query was made from
   116    116           query,               -- Fts5 query string
   117    117           nres,                -- Number of results
   118    118           timestamp DEFAULT CURRENT_TIMESTAMP
   119    119         );
   120         -
   121    120         INSERT INTO log(ip, query, nres) VALUES($ip, $query, $nRes);
   122    121       COMMIT;
   123    122     }
   124    123   
   125    124     db2 close
   126    125   }
   127    126   
................................................................................
   219    218   #   45.02 ms
   220    219   #
   221    220   proc ttime {script} {
   222    221     set t [lindex [time [list uplevel $script]] 0]
   223    222     if {$t>1000000} { return [format "%.2f s" [expr {$t/1000000.0}]] }
   224    223     return [format "%.2f ms" [expr {$t/1000.0}]]
   225    224   }
          225  +
          226  +proc searchchanges {} {
          227  +  global A
          228  +  if {![info exists A(q)]} return ""
          229  +
          230  +  set open {<span style="background-color:#d9f2e6">}
          231  +  set close {</span>}
          232  +  set query {
          233  +    SELECT url, version, idx, highlight(change, 3, $open, $close) AS text 
          234  +    FROM change($A(q)) ORDER BY rowid ASC
          235  +  }
          236  +
          237  +  set ret [subst {
          238  +    <p>Change log entries mentioning: <b>[htmlize $::A(q)]</b>
          239  +    <table border=0>
          240  +  }]
          241  +
          242  +  set s2 "style=\"margin-top:0\""
          243  +  set s1 "style=\"font-size:larger; text-align:left\" class=nounderline"
          244  +  set prev ""
          245  +  db eval $query {
          246  +    if {$prev!=$version} {
          247  +      append ret [subst {
          248  +        <tr> <td $s1 valign=top> <a href=$url>$version</a> <td> <ul $s2>
          249  +      }]
          250  +      set prev $version
          251  +    }
          252  +    append ret [subst { <li value=$idx> ($idx) $text }]
          253  +  }
          254  +
          255  +  append ret "</table>"
          256  +  append ret "<center><p>You can also see the <a href=changes.html>entire"
          257  +  append ret " changelog as a single page</a> if you wish.</center>"
          258  +
          259  +  return $ret
          260  +}
   226    261   
   227    262   proc searchresults {} {
   228    263     if {![info exists ::A(q)]} return ""
   229    264     #set ::A(q) [string map {' ''} $A(q)]
   230    265     #regsub -all {[^-/"A-Za-z0-9]} $::A(q) { } ::A(q)
   231    266   
   232    267     # Count the '"' characters in $::A(q). If there is an odd number of
................................................................................
   378    413     # If "admin=1" is specified, jump to the admin screen.
   379    414     if {[string match *admin* $::env(REQUEST_URI)]} {
   380    415       set ::PATH ../
   381    416       return [admin_list]
   382    417     }
   383    418   
   384    419     sqlite3 db search.d/search.db
          420  +
          421  +  set cmd searchresults
          422  +  if {[info exists A(s)] && $A(s)=="c"} {
          423  +    set cmd searchchanges
          424  +  }
   385    425   
   386    426     db transaction {
   387    427       set t [ttime { 
   388         -      if {[catch searchresults srchout]} {
          428  +      if {[catch $cmd srchout]} {
   389    429           set A(q) [string tolower $A(q)]
   390         -        set srchout [searchresults]
          430  +        set srchout [$cmd]
   391    431         }
   392    432         set doc $srchout
   393    433       }]
   394    434     }
          435  +  append doc "<center>"
   395    436     append doc "<p>Page generated by <a href='fts5.html'>FTS5</a> in about $t."
          437  +  append doc "</center>"
   396    438     return $doc
   397    439   
   398    440     # return [cgi_env_dump]
   399    441   }
   400    442   
   401    443   #=========================================================================
   402    444   
................................................................................
   418    460     if {[info exists ::A(q)]} {
   419    461       set initsearch [attrize $::A(q)]
   420    462       append title " - [htmlize $::A(q)]"
   421    463     } else {
   422    464       set initsearch {}
   423    465     }
   424    466     set document [document_header $title $::PATH $initsearch]
          467  +  append document [subst {
          468  +    <script>
          469  +      window.addEventListener('load', function() {
          470  +        var w = document.getElementById("searchmenu");
          471  +        w.style.display = "block";
          472  +
          473  +        document.getElementById("searchtype").value = "$::A(s)"
          474  +
          475  +        setTimeout(function(){
          476  +          var s = document.getElementById("searchbox");
          477  +          s.focus();
          478  +          s.select();
          479  +        }, 30);
          480  +      });
          481  +    </script>
          482  +  }]
   425    483     append document $res
   426    484   } else {
   427    485     set document "<pre>"
   428    486     append document "Error: $res\n\n"
   429    487     append document $::errorInfo
   430    488     append document "</pre>"
   431    489   }