Fossil

Check-in [fb6f1b7b]
Login

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

Overview
Comment:Automatically clean up the HTML that is generated by webbrowsers and by the Fossil wiki-to-html translator so that the HTML is easier to read in the wysiwyg editor.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | wysiwyg
Files: files | file ages | folders
SHA1:fb6f1b7b719f9f62322b6eb950ccf72cb86de4c6
User & Date: drh 2012-08-10 23:12:18
Context
2012-08-10
23:18
Reduce the maximum height of a wiki edit frame to 30 rows. check-in: e000f7f0 user: drh tags: wysiwyg
23:12
Automatically clean up the HTML that is generated by webbrowsers and by the Fossil wiki-to-html translator so that the HTML is easier to read in the wysiwyg editor. check-in: fb6f1b7b user: drh tags: wysiwyg
19:59
Add experimental support for WYSIWYG editing of wiki pages. check-in: 6cd9847f user: drh tags: wysiwyg
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/wiki.c.

260
261
262
263
264
265
266

267
268






269

270
271
272
273
274
275
276
...
358
359
360
361
362
363
364
365
366
367
368
369
370



371
372
373
374
375
376
377
  Blob wiki;
  Manifest *pWiki = 0;
  const char *zPageName;
  char *zHtmlPageName;
  int n;
  const char *z;
  char *zBody = (char*)P("w");


  if( zBody ){






    zBody = mprintf("%s", zBody);

  }
  login_check_credentials();
  zPageName = PD("name","");
  if( check_name(zPageName) ) return;
  isSandbox = is_sandbox(zPageName);
  if( isSandbox ){
    if( !g.perm.WrWiki ){
................................................................................
    @ <form method="post" action="%s(g.zTop)/wikiedit"><div>
    @ <textarea name="w" class="wikiedit" cols="80" 
    @  rows="%d(n)" wrap="virtual">%h(zBody)</textarea>
    @ <br />
    @ <input type="submit" name="preview" value="Preview Your Changes" />
  }else{
    /* Wysiwyg editing */
    Blob html;
    @ <form method="post" action="%s(g.zTop)/wikiedit"
    @  onsubmit="wysiwygSubmit()"><div>
    @ <input type="hidden" name="wysiwyg" value="1" />
    blob_zero(&html);
    wiki_convert(&wiki, &html, 0);



    wysiwygEditor("w", blob_str(&html), 60, n);
    blob_reset(&html);
    @ <br />
  }
  @ <input type="submit" name="submit" value="Apply These Changes" />
  login_insert_csrf_secret();
  @ <input type="hidden" name="name" value="%h(zPageName)" />







>


>
>
>
>
>
>
|
>







 







|



|
|
>
>
>







260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
...
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
  Blob wiki;
  Manifest *pWiki = 0;
  const char *zPageName;
  char *zHtmlPageName;
  int n;
  const char *z;
  char *zBody = (char*)P("w");
  int isWysiwyg = P("wysiwyg")!=0;

  if( zBody ){
    if( isWysiwyg ){
      Blob body;
      blob_zero(&body);
      htmlTidy(zBody, &body);
      zBody = blob_str(&body);
    }else{
      zBody = mprintf("%s", zBody);
    }
  }
  login_check_credentials();
  zPageName = PD("name","");
  if( check_name(zPageName) ) return;
  isSandbox = is_sandbox(zPageName);
  if( isSandbox ){
    if( !g.perm.WrWiki ){
................................................................................
    @ <form method="post" action="%s(g.zTop)/wikiedit"><div>
    @ <textarea name="w" class="wikiedit" cols="80" 
    @  rows="%d(n)" wrap="virtual">%h(zBody)</textarea>
    @ <br />
    @ <input type="submit" name="preview" value="Preview Your Changes" />
  }else{
    /* Wysiwyg editing */
    Blob html, temp;
    @ <form method="post" action="%s(g.zTop)/wikiedit"
    @  onsubmit="wysiwygSubmit()"><div>
    @ <input type="hidden" name="wysiwyg" value="1" />
    blob_zero(&temp);
    wiki_convert(&wiki, &temp, 0);
    blob_zero(&html);
    htmlTidy(blob_str(&temp), &html);
    blob_reset(&temp);
    wysiwygEditor("w", blob_str(&html), 60, n);
    blob_reset(&html);
    @ <br />
  }
  @ <input type="submit" name="submit" value="Apply These Changes" />
  login_insert_csrf_secret();
  @ <input type="hidden" name="name" value="%h(zPageName)" />

Changes to src/wikiformat.c.

1745
1746
1747
1748
1749
1750
1751















































































































        break;
      }
    }
    z += n;
  }
  free(renderer.aStack);
}






















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
        break;
      }
    }
    z += n;
  }
  free(renderer.aStack);
}

/*
** Get the next HTML token.
**
** z points to the start of a token.  Return the number of
** characters in that token.
*/
static int nextHtmlToken(const char *z){
  int n;
  if( z[0]=='<' ){
    n = markupLength(z);
    if( n<=0 ) n = 1;
  }else if( fossil_isspace(z[0]) ){
    for(n=1; z[n] && fossil_isspace(z[n]); n++){}
  }else{
    for(n=1; z[n] && z[n]!='<' && !fossil_isspace(z[n]); n++){}
  }
  return n;
}

/*
** Return true if z[] is the word zWord in any case.
*/
static int isWord(const char *z, const char *zWord, int nWord){
  return fossil_strnicmp(z, zWord, nWord)==0 && !fossil_isalpha(z[nWord]);
}

/*
** Attempt to reformat messy HTML to be easily readable by humans.
**
**    *  Try to keep lines less than 80 characters in length
**    *  Collapse white space into a single space
**    *  Put a blank line before:
**          <blockquote><center><code><hN><p><pre><table>
**    *  Put a newline after <br> and <hr>
**    *  Start each of the following elements on a new line:
**          <address><cite><dd><div><dl><dt><li><ol><samp>
**          <tbody><td><tfoot><th><thead><tr><ul>
**
** Except, do not do any reformatting inside of <pre>...</pre>
*/
void htmlTidy(const char *zIn, Blob *pOut){
  int n;
  int nPre = 0;
  int iCur = 0;
  while( zIn[0] ){
    n = nextHtmlToken(zIn);
    if( zIn[0]=='<' && n>1 ){
      if( isWord(zIn, "<pre", 4) ){
        if( iCur && nPre==0 ){ blob_append(pOut, "\n", 1); iCur = 0; }
        nPre++;
      }else if( isWord(zIn, "</pre", 5) ){
        nPre--;
        if( nPre==0 ){ blob_append(pOut, "\n", 1); iCur = 0; }
      }else if( isWord(zIn, "<blockquote", 11)
             || isWord(zIn, "<center", 7)
             || (isWord(zIn, "<h", 2) && fossil_isdigit(zIn[2]))
             || isWord(zIn, "<p", 2)
             || isWord(zIn, "<table", 6) ){
        blob_append(pOut, "\n\n", 1 + (iCur>0));
        iCur = 0;
      }else if( isWord(zIn, "<dd", 3)
             || isWord(zIn, "<div", 4)
             || isWord(zIn, "<dl", 3)
             || isWord(zIn, "<dt", 3)
             || isWord(zIn, "<li", 3)
             || isWord(zIn, "<ol", 3)
             || isWord(zIn, "<td", 3)
             || isWord(zIn, "<th", 3)
             || isWord(zIn, "<tr", 3)
             || isWord(zIn, "<ul", 3) ){
        if( iCur>0 ) blob_append(pOut, "\n", 1);
        iCur = 0;
      }
      blob_append(pOut, zIn, n);
      iCur += n;
    }else if( fossil_isspace(zIn[0]) ){
      if( nPre ){
        blob_append(pOut, zIn, n);
      }else if( iCur>=70 ){
        blob_append(pOut, "\n", 1);
        iCur = 0;
      }else{
        blob_append(pOut, " ", 1);
        iCur++;
      }
    }else{
      blob_append(pOut, zIn, n);
      iCur += n;
    }
    zIn += n;
  }
  if( iCur ) blob_append(pOut, "\n", 1);
}

/*
** COMMAND: test-html-tidy
*/
void test_html_tidy(void){
  Blob in, out;
  int i;

  for(i=2; i<g.argc; i++){
    blob_read_from_file(&in, g.argv[i]);
    blob_zero(&out);
    htmlTidy(blob_str(&in), &out);
    blob_reset(&in);
    fossil_puts(blob_str(&out), 0);
    blob_reset(&out);
  }
}