summaryrefslogtreecommitdiff
path: root/www/customskin.md
diff options
context:
space:
mode:
Diffstat (limited to 'www/customskin.md')
-rw-r--r--www/customskin.md598
1 files changed, 598 insertions, 0 deletions
diff --git a/www/customskin.md b/www/customskin.md
new file mode 100644
index 0000000..2df2b13
--- /dev/null
+++ b/www/customskin.md
@@ -0,0 +1,598 @@
+# Skinning the Fossil Web Interface
+
+The Fossil web interface comes with a pre-configured look and feel. The default
+look and feel works fine in many situations. However, you may want to change
+the look and feel (the "skin") of Fossil to better suite your own individual tastes.
+This document provides background information to aid you in that task.
+
+## <a id="builtin"></a>Built-in Skins
+
+Fossil comes with [multiple built-in skins](/skins). If the default skin does not
+suite your tastes, perhaps one of the other built-in skins will work better.
+If nothing else, the built-in skins can serve as examples or templates that
+you can use to develop your own custom skin.
+
+The sources to these built-ins can
+be found in the Fossil source tree under the skins/ folder. The
+[skins/](/dir?ci=trunk&name=skins)
+folder contains a separate subfolder for each built-in skin, with each
+subfolders holding at least these five files:
+
+ * css.txt
+ * details.txt
+ * footer.txt
+ * header.txt
+ * js.txt
+
+Try out the built-in skins by using the --skin option on the
+[fossil ui](/help/ui) or [fossil server](/help/server) commands.
+
+## <a id="sharing"></a>Sharing Skins
+
+The skin of a repository is not part of the versioned state and does not
+"push" or "pull" like checked-in files. The skin is local to the
+repository. However, skins can be shared between repositories using
+the [fossil config](/help/configuration) command.
+The "fossil config push skin" command will send the local skin to a remote
+repository and the "fossil config pull skin" command will import a skin
+from a remote repository. The "fossil config export skin FILENAME"
+will export the skin for a repository into a file FILENAME. This file
+can then be imported into a different repository using the
+"fossil config import FILENAME" command. Unlike "push" and "pull",
+the "export" and "import" commands are able to move skins between
+repositories for different projects. So, for example, if you have a
+group of related repositories, you can develop a skin for one of them,
+then get a consistent look across all the repositories by exporting
+the skin from the first repository and importing into all the others.
+
+The file generated by "fossil config export" could be checked into
+one of your repositories and versioned, if desired. This will not
+automatically change the skin when looking backwards in time, but it
+will provide an historical record of what the skin used to be and
+allow the historical look of the repositories to be recreated if
+necessary.
+
+When cloning a repository, the skin of the new repository is initialized to
+the skin of the repository from which it was cloned.
+
+# Structure Of A Fossil Web Page
+
+Every HTML page generated by Fossil has the same basic structure:
+
+| Fossil-Generated HTML Header |
+| Skin Header |
+| Fossil-Generated Content |
+| Skin Footer |
+| Fossil-Generated HTML Footer |
+
+By default, Fossil starts every generated HTML page with this:
+
+ <html>
+ <head>
+ <base href="...">
+ <meta http-equiv="Content-Security-Policy" content="....">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>....</title>
+ <link rel="stylesheet" href="..." type="text/css">
+ </head>
+ <body class="FEATURE">
+
+Fossil used to require a static version of this in every skin’s Header
+area, but over time, we have found good cause to generate multiple
+elements at runtime.
+
+One such is the `FEATURE` element, being either the top-level HTTP
+request routing element (e.g. `doc`) or an aggregate feature class that
+groups multiple routes under a single name. A prime example is `forum`,
+which groups the `/forummain`, `/forumpost`, and `/forume2` routes,
+allowing per-feature CSS. For instance, to style `<blockquote>` tags
+specially for forum posts written in Markdown, leaving all other block
+quotes alone, you could say:
+
+ body.forum div.markdown blockquote {
+ margin-left: 10px;
+ }
+
+You can [override this generated HTML header](#override) by including a
+“`<body>`” tag somewhere in the Header area of the skin, but it is
+almost always best to limit a custom skin’s Header section to something
+like this:
+
+<div class="sidebar" id="version-2.24">Prior to Fossil 2.24, we used
+generic `<div>` elements to mark up these sections of the header, but we
+switched to these semantic tag names to give browser accessibility
+features more freedom to do intelligent things with the page content.
+Those who made custom skins based on the old way of doing things will
+need to track this change when upgrading, else the corresponding CSS
+will mistarget the page header elements. Also, if you’re using Fossil’s
+chat feature, failing to track this change will cause it to miscalculate
+the message area size, resulting in double scrollbars. Simply diffing
+your custom header in the skin editor against the stock version should
+be sufficient to show what you need to change.</div>
+
+
+ <header>
+ ...
+ </header>
+ <nav class="mainmenu" title="Main Menu">
+ ...
+ </nav>
+ <nav id="hbdrop" class="hbdrop" title="sitemap"></nav>
+
+See the stock skins’ headers for ideas of what to put in place of the
+ellipses.
+
+The Fossil-generated Content section immediately follows this Header.
+It will look like this:
+
+ <div class="content">
+ ... Fossil-generated content here ...
+ </div>
+
+After the Content is the custom Skin Footer section which should
+follow this template:
+
+ <footer>
+ ... skin-specific stuff here ...
+ </footer>
+
+As with the `<header>` change called out above, this, too, is a breaking
+change in Fossil 2.24.
+
+Finally, Fossil always adds its own footer (unless overridden)
+to close out the generated HTML:
+
+ </body>
+ </html>
+
+## <a id="mainmenu"></a>Changing the Main Menu Contents
+
+The actual text content of the skin’s main menu is not
+part of the skin proper if you’re using one of the stock skins.
+If you look at the Header section of the skin, you’ll find a
+`<div class="mainmenu">` element whose contents are set by a short
+[TH1](./th1.md) script from the contents of the **Main Menu** section of
+the Setup → Configuration screen.
+
+This feature allows the main menu contents to stay the same across
+different skins, so you no longer have to reapply menu customizations
+when trying different skins.
+
+See the [`capexpr`](./th1.md#capexpr) section of the TH1 docs for help
+on interpreting the default contents of this block.
+
+
+## <a id="override"></a>Overriding the HTML Header and Footer
+
+Notice that the `<html>`, `<head>`, and opening `<body>`
+elements at the beginning of the document,
+and the closing `</body>` and `</html>` elements at the end are automatically
+generated by Fossil. This is recommended.
+
+However, for maximum design flexibility, Fossil allows those elements to be
+supplied as part of the configurable Skin Header and Skin Footer.
+If the Skin Header contains the text "`<body`", then Fossil assumes that
+the Skin Header and Skin Footer will handle all of the `<html>`,
+`<head>`, and `<body>` text itself, and the Fossil-generated header and
+footer will be blank.
+
+When overriding the HTML Header in this way, you will probably want to use some
+of the [TH1 variables documented below](#vars) such as `$stylesheet_url`
+to avoid hand-writing code that Fossil can generate for you.
+
+# Designing, Debugging, and Installing A Custom Skin
+
+It is possible to develop a new skin from scratch. But a better and easier
+approach is to use one of the existing built-in skins as a baseline and
+make incremental modifications, testing after each step, to obtain the
+desired result.
+
+The skin is controlled by five files:
+
+<dl>
+<dt><b>css.txt</b></dt>
+
+<dd>The css.txt file is the text of the CSS for Fossil.
+Fossil might add additional CSS elements after
+the css.txt file, if it sees that the css.txt omits some
+CSS components that Fossil needs. But for the most part,
+the content of the css.txt is the CSS for the page.</dd>
+
+<dt><b>details.txt</b><dt>
+
+<dd>The details.txt file is short list of settings that control
+the look and feel, mostly of the timeline. The default
+details.txt file looks like this:
+
+<pre>
+pikchr-background: ""
+pikchr-fontscale: ""
+pikchr-foreground: ""
+pikchr-scale: ""
+timeline-arrowheads: 1
+timeline-circle-nodes: 1
+timeline-color-graph-lines: 1
+white-foreground: 0
+</pre>
+
+The three "timeline-" settings in details.txt control the appearance
+of certain aspects of the timeline graph. The number on the
+right is a boolean - "1" to activate the feature and "0" to
+disable it. The "white-foreground:" setting should be set to
+"1" if the page color has light-color text on a darker background,
+and "0" if the page has dark text on a light-colored background.
+
+If the "pikchr-foreground" setting
+is defined and is not an empty string then it specifies a
+foreground color to use for [pikchr diagrams](./pikchr.md). The
+default pikchr foreground color is black, or white if the
+"white-foreground" boolean is set. The "pikchr-background"
+settings does the same for the pikchr diagram background color.
+If the "pikchr-fontscale" and "pikchr-scale" values are not
+empty strings, then they should be floating point values (close
+to 1.0) that specify relative scaling of the fonts in pikchr
+diagrams and other elements of the diagrams, respectively.
+</dd>
+
+<dt><b>footer.txt</b> and <b>header.txt</b></dt>
+
+<dd>The footer.txt and header.txt files contain the Skin Footer
+and Skin Header respectively. Of these, the Skin Header is
+the most important, as it contains the markup used to generate
+the banner and menu bar for each page.
+
+Both the footer.txt and header.txt file are
+[processed using TH1](#headfoot) prior to being output as
+part of the overall web page.</dd>
+
+<dt><b>js.txt</b></dt>
+
+<dd>The js.txt file is optional. It is intended to be javascript.
+The complete text of this javascript might be inserted into
+the Skin Footer, after being processed using TH1, using
+code like the following in the "footer.txt" file:
+
+<pre>
+&lt;script nonce="$nonce"&gt;
+ &lt;th1&gt;styleScript&lt;/th1&gt;
+&lt;/script&gt;
+</pre>
+
+The js.txt file was originally used to insert javascript
+that controls the hamburger menu in the default skin. More
+recently, the javascript for the hamburger menu was moved into
+a separate built-in file. Skins that use the hamburger menu
+typically cause the javascript to be loaded by including the
+following TH1 code in the "header.txt" file:
+
+<pre>
+&lt;th1&gt;builtin_request_js hbmenu.js&lt;/th1&gt;
+</pre>
+
+The difference between `styleScript` and `builtin_request_js`
+is that the `styleScript` command interprets the file
+using TH1 and injects the content directly into the output
+stream, whereas the `builtin_request_js` command inserts the
+Javascript verbatim and does so at some unspecified future time
+down inside the Fossil-generated footer.
+You can use either
+approach in custom skins that you create.
+
+Note that the "js.txt" file is *not* automatically inserted into
+the generate HTML for a page. You, the skin designer, must
+cause the javascript to be inserted by issuing appropriate
+TH1 commands in the "header.txt" or "footer.txt" files.</dd>
+</dl>
+
+Developing a new skin is simply a matter of creating appropriate
+versions of these five control files.
+
+### Skin Development Using The Web Interface
+
+Users with admin privileges can use the Admin/Skin configuration page
+on the web interface to develop a new skin. The development of a new
+skin occurs without disrupting the existing skin. So you can work on
+a new skin for a Fossil instance while the existing skin is still in
+active use.
+
+The new skin is a "draft" skin. You initialize one of 9 draft skins
+to either the current skin or to one of the built-in skins. Then
+use forms to edit the 5 control files described above. The new
+skin can be tested after each edit. Finally, once the new skin is
+working as desired, the draft skin is "published" and becomes the
+new live skin that most users see.
+
+### Skin Development Using A Local Text Editor
+
+An alternative approach is to copy the five control files for your
+baseline skin into a temporary working directory (here called
+"./newskin") and then launch the [fossil ui](/help/ui) command
+with the "--skin ./newskin" option. If the argument to the --skin
+option contains a "/" character, then the five control files are
+read out of the directory named. You can then edit the control
+files in the ./newskin folder using you favorite text editor, and
+press "Reload" on your browser to see the effects.
+
+
+### Disabling The Web Browser Cache During Development
+
+Fossil is aggressive about asking the web browser to cache
+resources. While developing a new skin, it is often helpful to
+put your web browser into developer mode and disable the cache.
+If you fail to do this, then you might make some change to your skin
+under development and press "Reload" only to find that the display
+did not change. After you have finished work your skin, the
+caches should synchronize with your new design and you can reactivate
+your web browser's cache and take it out of developer mode.
+
+## <a id="headfoot"></a>Header and Footer Processing
+
+The `header.txt` and `footer.txt` control files of a skin are the HTML text
+of the Skin Header and Skin Footer, except that before being inserted
+into the output stream, the text is run through a
+[TH1 interpreter](./th1.md) that might adjust the text as follows:
+
+ * All text within &lt;th1&gt;...&lt;/th1&gt; is omitted from the
+ output and is instead run as a TH1 script. That TH1
+ script has the opportunity to insert new text in place of itself,
+ or to inhibit or enable the output of subsequent text.
+
+ * Text of the form "$NAME" or "$&lt;NAME&gt;" is replaced with
+ the value of the TH1 variable NAME. See the [TH1 Variables](#vars)
+ section for more information on the two possible variable formats.
+
+For example, first few lines of a typical Skin Header will look
+like this:
+
+ <header>
+ <div class="title"><h1>$<project_name></h1>$<title>/div>
+
+After variables are substituted by TH1, that will look more like this:
+
+ <header>
+ <div class="title"><h1>Project Name</h1>Page Title</div>
+
+As you can see, two TH1 variable substitutions were done.
+
+The same TH1 interpreter is used for both the header and the footer
+and for all scripts contained within them both. Hence, any global
+TH1 variables that are set by the header are available to the footer.
+
+## <a id="menu"></a>Customizing the ≡ Hamburger Menu
+
+The menu bar of the default skin has an entry to open a drop-down menu with
+additional navigation links, represented by the ≡ button (hence the name
+"hamburger menu"). The Javascript logic to open and close the hamburger menu
+when the button is clicked is usually handled by a script named
+"hbmenu.js" that is one of the [built-in resource files](/test-builtin-files)
+that are part of Fossil.
+
+The ≡ button for the hamburger menu is added to the menu bar by the following
+TH1 commands in the `header.txt` file, right before the menu bar links:
+
+ html "<a id='hbbtn' href='$home/sitemap'>&#9776;</a>"
+ builtin_request_js hbmenu.js
+
+The hamburger button can be repositioned between the other menu links (but the
+drop-down menu is always left-aligned with the menu bar), or it can be removed
+by deleting the above statements. The "html" statement inserts the appropriate
+`<a>` for the hamburger menu button (some skins require something slightly
+different - for example the ardoise skins wants "`<li><a>`"). The
+"builtin_request_js hbmenu.js" asks Fossil to include the "hbmenu.js"
+resource files in the Fossil-generated footer.
+
+The hbmenu.js script requires
+the following `<div>` element somewhere in your header, in which to build
+the hamburger menu.
+
+ <div id='hbdrop'></div>
+
+Out of the box, the contents of the panel is populated with the [Site
+Map](/sitemap), but only if the panel does not already contain any HTML
+elements (that is, not just comments, plain text or non-presentational white
+space). So the hamburger menu can be customized by replacing the empty `<div
+id='hbdrop'></div>` element with a menu structure knitted according to the
+following template:
+
+ <div id="hbdrop" data-anim-ms="400">
+ <ul class="columns" style="column-width: 20em; column-count: auto">
+ <!-- NEW GROUP WITH HEADING LINK -->
+ <li>
+ <a href="$home$index_page">Link: Home</a>
+ <ul>
+ <li><a href="$home/timeline">Link: Timeline</a></li>
+ <li><a href="$home/dir?ci=tip">Link: File List</a></li>
+ </ul>
+ </li>
+ <!-- NEW GROUP WITH HEADING TEXT -->
+ <li>
+ Heading Text
+ <ul>
+ <li><a href="$home/doc/trunk/www/customskin.md">Link: Theming</a></li>
+ <li><a href="$home/doc/trunk/www/th1.md">Link: TH1 Scripts</a></li>
+ </ul>
+ </li>
+ <!-- NEXT GROUP GOES HERE -->
+ </ul>
+ </div>
+
+The custom `data-anim-ms` attribute can be added to the panel element to direct
+the Javascript logic to override the default menu animation duration of 400 ms.
+A faster animation duration of 80-200 ms may be preferred for smaller menus. The
+animation is disabled by setting the attribute to `"0"`.
+
+
+## <a id="vars"></a>TH1 Variables
+
+Before expanding the TH1 within the header and footer, Fossil first
+initializes a number of TH1 variables to values that depend on
+repository settings and the specific page being generated.
+
+Variables holding text that is loaded from "external, potentially untrusted"
+sources (including the repository settings) are treated as [tainted strings]
+(./th1.md#taint) and must be noted in the `$<NAME>` form, instead of `$NAME`,
+or they may trigger an error (see the linked document for details). The
+`$<NAME>` form corresponds to the TH1 statement `puts [ htmlize "$NAME" ]`,
+where the [htmlize](./th1.md#htmlize) function escapes the tainted string,
+making it safe for output in HTML code.
+
+
+ * **`project_name`** - The project_name variable is filled with the
+ name of the project as configured under the Admin/Configuration
+ menu. This is a [tainted string](./th1.md#taint) variable and must
+ be used as `$<project_name>`.
+
+ * **`project_description`** - The project_description variable is
+ filled with the description of the project as configured under
+ the Admin/Configuration menu. This is a [tainted string]
+ (./th1.md#taint) variable and must be used as `$<project_description>`.
+
+ * **`mainmenu`** - The mainmenu variable contains a TCL list with the main
+ menu entries. See the [mainmenu](/help/mainmenu) setting for details.
+
+ * **`title`** - The title variable holds the title of the page being
+ generated.
+
+ The title variable is special in that it is deleted after
+ the header script runs and before the footer script. This is
+ necessary to avoid a conflict with a variable by the same name used
+ in my ticket-screen scripts.
+
+ * **`baseurl`** - The root of the URL namespace for this server.
+
+ * **`secureurl`** - The same as $baseurl except that if the scheme is
+ "http:" it is changed to "https:"
+
+ * **`home`** - The $baseurl without the scheme and hostname. For example,
+ if the $baseurl is "http://projectX.com/cgi-bin/fossil" then the
+ $home will be just "/cgi-bin/fossil".
+
+ * **`index_page`** - The landing page URI as
+ specified by the Admin/Configuration setup page.
+
+ * **`current_page`** - The name of the page currently being processed,
+ without the leading "/" and without query parameters.
+ Examples: "timeline", "doc/trunk/README.txt", "wiki".
+
+ * **`current_checkin`** - The [check-in name](./checkin_names.wiki) to
+ which the current
+ [/ci](/help/www/ci),
+ [/dir](/help/www/dir),
+ [/tree](/help/www/tree),
+ [/timeline](/help/www/timeline) or
+ [/vinfo](/help/www/vinfo)
+ page refers, or undefined for all other pages. This variable is
+ derived from query parameters and is therefore a [tainted string]
+ (./th1.md#taint).
+
+ * **`csrf_token`** - A token used to prevent cross-site request forgery.
+
+ * **`default_csp`** - [Fossil’s default CSP](./defcsp.md) unless
+ [overridden by custom TH1 code](./defcsp.md#th1). Useful within
+ the skin for inserting the CSP into a `<meta>` tag within [a
+ custom `<head>` element](#headfoot).
+
+ * **`nonce`** - The value of the cryptographic nonce for the request
+ being processed.
+
+ * **`release_version`** - The release version of Fossil. Ex: "1.31"
+
+ * **`manifest_version`** - A prefix on the check-in hash of the
+ specific version of fossil that is running. Ex: "\[47bb6432a1\]"
+
+ * **`manifest_date`** - The date of the source-code check-in for the
+ version of fossil that is running.
+
+ * **`compiler_name`** - The name and version of the compiler used to
+ build the fossil executable.
+
+ * **`login`** - This variable only exists if the user has logged in.
+ The value is the username of the user.
+
+ * **`stylesheet_url`** - A URL for the internal style-sheet maintained
+ by Fossil.
+
+ * **`logo_image_url`** - A URL for the logo image for this project, as
+ configured on the Admin/Logo page.
+
+ * **`background_image_url`** - A URL for a background image for this
+ project, as configured on the Admin/Logo page.
+
+All of the above are variables in the sense that either the header or the
+footer is free to change or erase them. But they should probably be treated
+as constants. New predefined values are likely to be added in future
+releases of Fossil.
+
+
+## <a id="procedure"></a>Suggested Skin Customization Procedure
+
+Developers are free, of course, to develop new skins using any method they
+want, but the following is a technique that has worked well in the past and
+can serve as a starting point for future work:
+
+ 1. Select a built-in skin that is closest to the desired look. Make
+ copies of the css, footer, and header into files name "css.txt",
+ "details.txt",
+ "footer.txt", and "header.txt" in some temporary directory.
+
+ If the Fossil source code is available, then these three files can
+ be copied directly out of one of the subdirectories under skins. If
+ sources are not easily at hand, then a copy/paste out of the
+ CSS, footer, and header editing screens under the Admin menu will
+ work just as well. The important point is that the three files
+ be named exactly "css.txt", "footer.txt", and "header.txt" and that
+ they all be in the same directory.
+
+ 2. Run the [fossil ui](/help/ui) command with an extra
+ option "--skin SKINDIR" where SKINDIR is the name of the directory
+ in which the three txt files were stored in step 1. This will bring
+ up the Fossil website using the tree files in SKINDIR.
+
+ 3. Edit the *.txt files in SKINDIR. After making each small change,
+ press Reload on the web browser to see the effect of that change.
+ Iterate until the desired look is achieved.
+
+ 4. Copy/paste the resulting css.txt, details.txt,
+ header.txt, and footer.txt files
+ into the CSS, details, header, and footer configuration screens
+ under the Admin/Skins menu. Alternately, import them using the
+ process described below.
+
+An alternative to step 4 is to convert the skin files into a form
+which can be imported into a repository using `fossil config import`.
+It requires compiling [a small tool from the fossil source
+tree](/file/tools/skintxt2config.c):
+
+>
+```
+$ cc -o s2c /path/to/fossil/checkout/tools/skintxt2config.c
+```
+
+With that in place, the custom skin files can be converted with:
+
+>
+```
+$ ./s2c yourskin/*.txt > skin.config
+```
+
+It can be imported into an arbitrary fossil repository with:
+
+>
+```
+$ fossil config import skin.config
+```
+
+And it can be pushed to a remote repository with:
+
+>
+```
+$ fossil config push skin
+```
+
+That approach has proven to be an effective way to locally develop
+skin changes then push them to a "live" site.
+
+
+## See Also
+
+* [Customizing the Timeline Graph](customgraph.md)