File: genhtml.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<!--GENHTML INSERT ^^ ================================================================-->
<!--
12/15: Add a doctype spec on line 1 so IE does fixed footer positioning at bottom.
But use HTML 4 (not 5) spec, so images in tables look as they did with no doctype.
Makes some things render diff (e.g, tables at top, and having hdrs), but no worse.
More details: https://en.wikipedia.org/wiki/Quirks_mode#Comparison_of_document_types.
-->
<!--END INSERT========================================================================-->


<HTML>

<HEAD>

<!-- META=Unicode type, STYLE=css link, SCRIPT=analytics  -->
<!-- feb18: STYLE now includes a viewport meta for mobile -->

<!--GENHTML INSERT====================================================================-->

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<!--
For this file only: UTF-8 Unicode encoding, for non-ASCII or non-English characters.
If omitted, browsers may guess, but often fall back on US-ASCII or user settings.
Update Dec-2018: move the <meta> encoding declaration above this comment, and 
the _META_ genhtml tag to the top of <head> if needed, so <meta> is in the first 
1024 bytes of the file per HTML5 standard.  Nonconforming pages work fine in all 
20+ browsers tested, though Firefox issues a warning in its web console, and some
may restart the page parse - a minor performance penalty.  Not an issue in thumbspage 
output, app user guides, showcode pages, or unzipped programs' Apache index pages. 
-->
<!--END INSERT========================================================================-->


<!--GENHTML INSERT====================================================================-->
<!--
Recoded Aug-18 to use relative path, after broken by https:// conversion: can't mix 
http:// page resources (see .htaccess note).  This required regenerating and uploading 
all .html files, but not hundreds of manual page edits - genhtml works!  Formerly 
used ICON-DEFAULT, which has now-dated docs on icon links and filetypes in general.
An icon file in the root folder suffices on some (but not all) web servers.
-->

<link rel="shortcut icon" type="image/x-icon" href="favicon.ico" />

<!--END INSERT========================================================================-->


<!--GENHTML INSERT====================================================================-->
<!--this insert serves *TWO* purposes: stylesheet and mobile viewport-->

<!--
Nov-15: CSS file, code in <HEAD>, for fonts, borders, navbars, code, etc.
This could also use an in-page <STYLE> sheet, as genhtml pastes any text.
-->

<link rel="stylesheet" type="text/css" href="_main.css">

<!--
Feb-18: Add a mobile-friendly viewport tag to every page's HEAD.
Fits content to device width, no zoom (user may), impacts MANY formats.
Extend STYLE instead of adding a new insert to avoid all-page updates.
Mobile support required other redesign: toolbar, code blocks, images,... 
-->
 
<meta name="viewport" content="width=device-width, initial-scale=1.0">

<!--END INSERT========================================================================-->


<!--GENHTML INSERT====================================================================-->
<!--
7/6/14: Google Analytics JavaScript (JS) code in <HEAD> (normally) - in two flavors.
Used only to prioritize high-traffic pages for dev work, iff JS and tracker enabled. 

The former/defunct training site's id: ga('create', 'UA-52578333-1', 'auto').
The book site's id, now used for all:  ga('create', 'UA-52579036-1', 'auto').
JS is also used if enabled for thumbspage galleries, Top buttons, TOCs, etc.

Jun-2019: tell Google Analytics to anonymize IP address on receipt for privacy.
More: https://developers.google.com/analytics/devguides/collection/analyticsjs/.

Oct-2022: install a GA4 tag (i.e., script) alongside the prior UA tag.  UA tags
will stop collecting data in 2023.  It's okay to use both until the cutover (and
Google advises doing so), but the UA tag will be pointless after that and should
be removed.  This handles genhtml-insert clients; others get tags by running
insert-analytics.py in package-publishing scripts.  Also per Google: "In Google 
Analytics 4, IP anonymization is not necessary since IP addresses are not logged
or stored".  Let's hope so... -->


<!-- 1) Universal Analytics tag (custom): stops collecting data on Jul-1-2023 -->

<SCRIPT>
  // Start async JS-file fetch, if not already cached

  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
  })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

  // Queue actions to run in order after async JS-file fetch finished

  ga('create', 'UA-52579036-1', 'auto');       // Create tracker object (and queue)
  ga('set', 'anonymizeIp', true);              // Anonymize IP addr (&aip) [Jun-2019]
  ga('send', 'pageview');                      // Send page-view event now 
</SCRIPT>


<!-- 2) Google Analytics 4 tag: added to site Oct-2022 (okay to keep UA tag) -->

<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-J8CTEZHX3L"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());

  gtag('config', 'G-J8CTEZHX3L');
</script>

<!--END INSERT========================================================================-->


<STYLE>
/* local styles not in _main.css */

/* aug18: notebox now uses common version in _main.css */
/* sep19: notebox (and its .belownote) now unused here */ 

LI {                       /* feb18 mobile: redesign by-date lists for mobile */
    margin-bottom: 8px;    /* all double-space, else hard to read or tap; sep20: 5=>8 */
}

DT {                       /* sep20: was .dlspace, but no other <dt>s here */
    margin-top: 8px;       /* aug18: for <li> converted to <dl> */
}

H2 {
    background-color: tan;          /* nov21: was too light: #eeeeee; */
    margin-bottom: 25px;            /* nov21: more wtspace below */
    margin-top: 32px;
    padding-left: 2px;     /* dec18: add space to left of title text */
}

.topspace {
    margin-top: 20px;      /* aug18: more whitespace (now just some lists) */
}

.belownote {
    margin-top: 40px;      /* sep20: notebox spacing: now unused ('new' note dropped) */
}

</STYLE>

<TITLE>genhtml - Web-Page Macros Utility</TITLE> 

</HEAD>

<BODY>


<!-- ====================================================================== -->


<H1><I>genhtml</I> &mdash; Static HTML Inserts for Website Files</H1>

<!-- Sep 2020: drop the "New" box (2017 updates no longer are) -->

<P>
This is the home of <I>genhtml</I>, a Python script used to 
construct most of the web pages published at this site.  With genhtml,
site-wide updates are easy, because common page components are split 
off to automatic inserts and referenced by name.
Moreover, genhtml's page inserts do not require a web server,
which makes them useful in off-line roles such as documentation. 

<P>
This page describes genhtml's use cases and mechanics, and provides
download links.  If you're looking for a quick example of genhtml 
in action, check out the 
<A HREF="cgi/showcode.py?name=genhtml/__docs__/genhtml.html">template</A> of 
the page you are viewing; one of the 
<A HREF="cgi/showcode.py?name=genhtml/__docs__/genhtml--STYLE.txt">inserts</A>
it references; and its genhtml 
<A HREF="cgi/showcode.py?name=genhtml.html">expansion</A>.
To dive right in, read the docstring of the <A HREF="genhtml/genhtml.py">script</A>,
and find genhtml's usage in this site's master publishing 
<A HREF="genhtml/__docs__/PUBLISH.py">utility</A>.
And for the full story, read on here.


<!-- ====================================================================== -->


<H2>Overview</H2>

<P>
This Python 3.X program provides basic <I>HTML macro</I> functionality,
which you invoke as part of your page-building workflow.
It replaces keys in a folder's HTML-template files with the content 
of correspondingly named insert files.  The net effect automatically 
updates static web pages when any common content they share is changed.
Among its features, this program has:

<DL>
<P>
<DT>Automatic dependency tracking
    <DD>HTML files are regenerated whenever&mdash;and only when&mdash;their 
    templates or any inserts they use have changed

<DT class=dlspace>Configurable Unicode support
    <DD>Encodings in a sequence are tried in turn for each HTML template file

<DT class=dlspace>One-level nested inserts
    <DD>Insert files can insert other insert files for added flexibility

<DT class=dlspace>Automatic generation-date insertion
    <DD>Built-in date keys support multiple formats
</DL>

<P>
This script addresses only static content: common text that can change over time,
but need not be generated on each new page request from a server.  For such content,
though, this program is a simple alternative to:

<UL>
<LI>Mass cut-and-paste edits, which are prohibitively tedious

<LI>JavaScript hacks on the client, which users may disable

<LI>PHP or Apache inserts on the server, which make your pages 
    unviewable offline

<LI>Unix cpp + make, which may not be present on every platform,
    and requires manual makefiles

<LI>HTML preprocessors, which have many of cpp's tradeoffs, 
    and are overkill for the use case
</UL>

<P>
By comparison, Server Side 
<A HREF="https://en.wikipedia.org/wiki/Server_Side_Includes">Includes</A>
provides a standard and reasonable inserts tool for pages which will only 
ever be viewed online.  genhtml can do similar work by building pages on
your development machine prior to uploads, but its server-less model 
also allows its results to be viewed in full offline, and applies to 
non-web tasks such as program documentation. 

<P>
Besides its utility, this program uses and requires only Python 3.X,
runs on any platform that Python 3.X supports (including most PCs and
smartphones), and illustrates a typical role for Python code in 
content-creation pipelines.


<!-- ====================================================================== -->


<H2>Resources</H2>

<P>
See the main script's docstring and other items below for usage details.


<P class=topspace>
<B><I>Code and docs</I></B>:
<UL>
<LI><A HREF="genhtml/genhtml.py">genhtml.py</A> &mdash; the main script's source (634 lines, 1/2 docstring)
</UL>


<P class=topspace>
<B><I>Example</I></B>:
<UL>
<LI><A HREF="cgi/showcode.py?name=genhtml/Html-templates/test1.html">Template page</A> &mdash; with insert targets

<LI><A HREF="genhtml/Html-inserts/FOOTERMAIN.txt">Insert file</A> &mdash; filename gives template key 

<LI><A HREF="genhtml/Html-inserts/FOOTER-COMMON.txt">Nested insert</A> &mdash; referenced in prior item

<LI><A HREF="cgi/showcode.py?name=genhtml/Complete/test1.html">Generated page</A> &mdash; with inserts applied

<LI><A HREF="genhtml/Complete/test1.html">Generated page</A> &mdash; as rendered by your browser
</UL>


<P class=topspace>
<B><I>Usage</I></B>:
<UL>
<LI><A HREF="genhtml/__docs__/PUBLISH.py">Site publishing script</A> &mdash; runs genhtml automatically

<LI><A HREF="genhtml/__docs__/run-log.txt">Run log examples</A> &mdash; basic script interaction

<LI><A HREF="genhtml/__docs__/console.png">Console screenshot</A> &mdash; session console capture

<LI><A HREF="genhtml/__docs__">Docs folder</A> &mdash; assorted documentation augmenting the script's docstring
</UL>


<!-- ====================================================================== -->


<H2>Download</H2>

<P>
Use the following to fetch genhtml, or view its unzipped content.

<UL>
<LI><A HREF="genhtml/genhtml.zip">genhtml.zip</A> &mdash; with all tests, docs, and examples</A>

<LI><A HREF="genhtml/">Unzipped content online</A> &mdash; script, docs, more examples and test pages
</UL>
</P>

<P>
This program was last changed: <B>March 2022</B>.     <!-- or pagegen date: October 23, 2022 -->

<P>
<I>Recent upgrades</I>: genhtml's latest version retries page saves with UTF-8, if 
their saves fail with the encoding used to load their templates.  This allows insert 
files to use broader Unicode character sets than their page-template clients. 

<P>genhtml's prior version explicitly handles <code>.*</code> Mac/Unix cruft files in 
inserts and templates folders, including both <code>.DS_Store</code> Finder files and 
any <code>._*</code> AppleDouble resource-fork files on non-Mac drives.  Both are skipped
in inserts to avoid errors, but are simply copied like other non-HTML in templates 
because more may crop up before site publication; filter later with your zip or upload 
tools (e.g., <code>-skipcruft</code> in <A HREF="ziptools.html">ziptools</A>).

<P>
For more code examples, see the
<A HREF="programs.html">programs</A> page.  
</P>


<!-- ====================================================================== -->


<!--GENHTML INSERT====================================================================-->
<!--
Nov15: added via genhtml.py, to avoid pasting footer in every file on changes.
See learning-python.com/genhtml.html for other options and their tradeoffs.
-->

</P>

<!--Feb18: make table responsive, for mobile-friendly scrollbar on small screens -->
<BR><BR>
<DIV class=footerdiv>
<TABLE class=footertable bgcolor=tan>

<!-- NESTED INSERT: can't nest > 2 deep -->      

<!-- gif now is Home, not python.org  -->
<!-- scale larger gif for better res  -->
<!-- border=0 only for IE img links   -->
<!-- _main.css center aligns all <td> -->
<!-- now narrower to avoid scrollbars -->

<TR>

<TD>
  <A class=blocklinkbar href="index.html">
  <IMG SRC="PythonPowered.gif" border=0 width=55 height=22
       ALT="[Home page]" TITLE="Home page"></A>  
<TD>
  <A class=blocklinkbar HREF="index-book-links.html">Books</A>
<TD>
  <A class=blocklinkbar HREF="programs.html">Code</A>
<TD>
  <A class=blocklinkbar HREF="posts.html">Blog</A>
<TD>
  <A class=blocklinkbar HREF="about-python.html">Python</A>
<TD>
  <A class=blocklinkbar HREF="formalbio.html">Author</A>
<TD>
  <A class=blocklinkbar HREF="training.html">Train</A>
<TD>
  <A class=blocklinkbar HREF="sitesearch.html">Find</A>
<TD>
  <A class=blocklinkbar HREF="mailto:lutz@learning-python.com">&copy;M.Lutz</A>

<!--DEFUNCT
<TD>
  <A class=blocklinkbar HREF="mailto:lutz@learning-python.com">Email</A>
<TD>
  <A class=blocklinkbar HREF="#">Top</A>
DEFUNCT-->

</TR>

<!-- END NESTED INSERT -->

</TABLE>
</DIV>

<!--END INSERT========================================================================-->


</BODY>
</HTML>



[Home page] Books Code Blog Python Author Train Find ©M.Lutz