Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Fix a bug in the markdown_to_html() routine in finding the title of the document. *This change requires a search index rebuild*. Begin adding documentation on how the header/footer mechanism works. |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | trunk |
| Files: | files | file ages | folders |
| SHA1: |
e214a576ea0dc1c88f2f6e5c39cf161d |
| User & Date: | drh 2015-02-16 19:27:03.540 |
Context
|
2015-02-16
| ||
| 20:15 | More documentation on theming and creating custom skins. ... (check-in: c397fe5c44 user: drh tags: trunk) | |
| 19:27 | Fix a bug in the markdown_to_html() routine in finding the title of the document. *This change requires a search index rebuild*. Begin adding documentation on how the header/footer mechanism works. ... (check-in: e214a576ea user: drh tags: trunk) | |
| 13:41 | Enhance the --skin option so that it can be a directory holding the three skin files. ... (check-in: bfd413bf1e user: drh tags: trunk) | |
Changes
Changes to src/markdown_html.c.
| ︙ | ︙ | |||
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
i++;
}
}
}
/* HTML block tags */
static void html_prolog(struct Blob *ob, void *opaque){
INTER_BLOCK(ob);
BLOB_APPEND_LITTERAL(ob, "<div class=\"markdown\">\n");
}
static void html_epilog(struct Blob *ob, void *opaque){
INTER_BLOCK(ob);
BLOB_APPEND_LITTERAL(ob, "</div>\n");
}
| > > > > | 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
i++;
}
}
}
/* HTML block tags */
/* Size of the prolog: "<div class='markdown'>\n" */
#define PROLOG_SIZE 23
static void html_prolog(struct Blob *ob, void *opaque){
INTER_BLOCK(ob);
BLOB_APPEND_LITTERAL(ob, "<div class=\"markdown\">\n");
assert( blob_size(ob)==PROLOG_SIZE );
}
static void html_epilog(struct Blob *ob, void *opaque){
INTER_BLOCK(ob);
BLOB_APPEND_LITTERAL(ob, "</div>\n");
}
|
| ︙ | ︙ | |||
124 125 126 127 128 129 130 |
struct Blob *text,
int level,
void *opaque
){
struct Blob *title = opaque;
/* The first header at the beginning of a text is considered as
* a title and not output. */
| | < | 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
struct Blob *text,
int level,
void *opaque
){
struct Blob *title = opaque;
/* The first header at the beginning of a text is considered as
* a title and not output. */
if( blob_size(ob)<=PROLOG_SIZE && blob_size(title)==0 ){
BLOB_APPEND_BLOB(title, text);
}
INTER_BLOCK(ob);
blob_appendf(ob, "<h%d>", level);
BLOB_APPEND_BLOB(ob, text);
blob_appendf(ob, "</h%d>", level);
}
|
| ︙ | ︙ |
Added www/customskin.md.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 |
Customizing Fossil's Look
=========================
Every HTML page generated by Fossil has the following basic structure:
<blockquote><table border=1 cellpadding=10><tbody>
<tr><td style='background-color:lightblue;'>Header</td></tr>
<tr><td style='background-color:lightgreen;'>Content</td></tr>
<tr><td style='background-color:lightblue;'>Footer</td></tr>
</tbody></table></blockquote>
The header and footer control the "look" of Fossil pages. Those
two sections can be customized separately for each repository to
develop a new theme.
The header will normally look something like this:
<html>
<head> ... </head>
<body>
... top banner and menu bar ...
<div class='content'>
And the footer will look something like this:
</div>
... bottom material ...
</body>
</html>
The <head> element in the header will normally reference the
/style.css CSS file that Fossil stores internally.
The middle "content" section of Fossil-generated pages is not normally
customizable. The appearance of Fossil is mostly governed by the CSS,
header, and footer, all of which are changeable on a per-repository
basis. We call the bundle of built-in CSS, header, and footer a "skin".
Built-in Skins
--------------
Fossil comes with several built-in skins. The sources to these built-ins can
be found in the Fossil source tree under the skins/ folder. The skins/
folder contains a separate subfolder for each built-in skin, with each
subfolders holding three files, "css.txt", "footer.txt", and "header.txt",
that describe the CSS, footer, and header for that skin, respectively.
The skin of a repository can be changed to any of the built-in skins using
the web interface by going to the /setup_skin web page (requires Admin
privileges) and clicking the appropriate button. Or, the --skin command
line option can be used for the
[fossil ui](../../../help?cmd=ui) or
[fossil server](../../../help?cmd=server) commands to force that particular
instance of Fossil to use the specified built-in skin.
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?cmd=configuration) command.
The "fossil config push skin" 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 new repository is initialized to
the skin of the repository from which it was cloned.
Header And Footer
-----------------
The header.txt and footer.txt files of a scan are merely the HTML text
of the header and footer. Except, that text is allowed to contain
embedded [TH1](./th1.md) script to modify or change its content.
With the header or footer, all text between <th1>...</th1>
is run as a TH1 script. And elements of the form <$NAME> are
replaced by the value of the NAME variable in TH1.
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.
TH1 Variables
-------------
Before expanding the TH1 within the header and footer, Fossil first
initializes a number of TH1 variables to values that depend on
respository settings and the specific page being generated.
* **project_name** - The project_name variable is filled with the
name of the project as configured under the Admin/Configuration
menu.
* **title** - The title variable holds the title of the page being
generated. This 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".
* **csrf_token** - A token used to prevent cross-site request forgery.
* **release_version** - The release version of Fossil. Ex: "1.31"
* **manifest_version** - A prefix on the SHA1 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.
* **log\_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.
|
Added www/th1.md.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
TH1 Scripts
===========
TH1 is a very small scripting language used to help generate web-page
content in Fossil.
Origins
-------
TH1 began as a minimalist reimplementation of the TCL scripting language.
There was a need to test the SQLite library on Symbian phones, but at that
time all of the test cases for SQLite were written in Tcl and Tcl could not
be easily compiled on the SymbianOS. So TH1 was developed as a cut-down
version of TCL that would facilitate running the SQLite test scripts on
SymbianOS.
The testing of SQLite on SymbianOS was eventually accomplished by other
means. But Fossil was first being designed at about the same time.
Early prototypes of Fossil were written in pure TCL. But as the development
shifted toward the use of C-code, the need arose to have a TCL-like
scripting language to help with code generation. TH1 was small and
light-weight and used minimal resources and seemed ideally suited for the
task.
The name "TH1" stands "Test Harness 1", since that was its original purpose.
Overview
--------
TH1 is a string-processing language. All values are strings. Any numerical
operations are accomplished by converting from string to numeric, performing
the computation, then converting the result back into a string. (This might
seem inefficient, but it is faster than people imagine, and numeric
computations do not come up very often for the kinds of work that TH1 does,
so it has never been a factor.)
A TH1 script consist of a sequence of commands.
Each command is terminated by the first (unescaped) newline or ";" character.
The text of the command (excluding the newline or semicolon terminator)
is broken into space-separated tokens. The first token is the command
name and subsequent tokens are the arguments. In this since, TH1 syntax
is similar to the familiar command-line shell syntax.
A token is any sequence of characters other than whitespace and semicolons.
Or, all text without double-quotes is a single token even if it includes
whitespace and semicolons. Or, all text without nested {...} pairs is a
single token.
The nested {...} form of tokens is important because it allows TH1 commands
to have an appearance similar to C/C++. It is important to remember, though,
that a TH1 script is really just a list of text commands, not a context-free
language with a grammar like C/C++. This can be confusing to long-time
C/C++ programmers because TH1 does look a lot like C/C++. But the semantics
of TH1 are closer to FORTH or Lisp than they are to C.
Consider the "if" command in TH1.
if {$current eq "dev"} {
puts "hello"
} else {
puts "world"
}
The example above is a single command. The first token, and the name
of the command, is "if".
The second token is '$current eq "dev"' - an expression. (The outer {...}
are removed from each token by the command parser.) The third token
is the 'puts "hello"', with its whitespace and newlines. The fourth token
is "else". And the fifth and last token is 'puts "world"'.
The "if" command word by evaluating its first argument (the second token)
as an expression, and if that expression is true, evaluating its
second argument (the third token) as a TH1 script.
If the expression is false and the third argument is "else" then
the fourth argument is evaluated as a TH1 expression.
So, you see, even though the example above spans five lines, it is really
just a single command.
Summary of Core TH1 Commands
----------------------------
The original TCL language after when TH1 is modeled has a very rich
repetoire of commands. TH1, as it is designed to be minimalist and
embedded has a greatly reduced command set. The following bullets
summarize the commands available in TH1:
* break
* catch SCRIPT ?VARIABLE?
* continue
* error ?STRING?
* expr EXPR
* for INIT-SCRIPT TEST-EXPR NEXT-SCRIPT BODY-SCRIPT
* if EXPR SCRIPT (elseif EXPR SCRIPT)* ?else SCRIPT?
* info exists VARNAME
* lindex LIST INDEX
* list ARG ...
* llength LIST
* proc NAME ARG-LIST BODY-SCRIPT
* rename OLD NEW
* return ?-code CODE? ?VALUE?
* set VARNAME VALUE
* string compare STR1 STR2
* string first NEEDLE HAYSTACK ?START-INDEX?
* string is CLASS STRING
* string last NEEDLE HAYSTACK ?START-INDEX?
* string length STRING
* string range STRING FIRST LAST
* string repeat STRING COUNT
* unset VARNAME
* uplevel ?LEVEL? SCRIPT
* upvar ?FRAME? OTHERVAR MYVAR ?OTHERVAR MYVAR?
All of the above commands works as in the original TCL. Refer to the
TCL documentation for details.
|