# How to ... with SBWG?

This file is being expanded alongside of SBWG itself. Some answers may be outdated by now. Sometimes I read through them to reflect changes and new features though.
So all answers here should be reasonable up-to-date and usually still correct.


## How to install SBWG on a computer or server?

There is no necessary installation routine. You can just unpack the script file, make it executable and run it with Bash. For a more detailed guide see the INSTALL
file.


## How to set up a new website?

SBWG comes with an `examples` directory which contains the source files of a small web site that can be built with SBWG. You can copy this directory and build your
web site according to the example. Please read the INSTALL file for instructions on how to set up a new web site based on the example web site.


## How to post a new blog entry?

Create an entry source file in the `entries` directory. The file should start with tags that provide meta information like the entry's title, creation date,
categories and so on. Everything below that is the content of the entry. There is a more detailed description of the available tags in the "Tags" section in the
README file.

You can create this file from scratch, use the `genentry` script that is included in this package, copy an existing entry file or find your own way of creating new
files locally or on the web server. It's just a text file. There are many possibilities like using templates in your favourite text editor or writing your own
script that generates a new entry.

The next time the web site is generated, the new entry will be included in the weblog view and on the tagpages for the tags that you defined in the entry file.


## How to publish all changes?

After you have created new or changed existing content, you have to re-generate the website. There are different options for (re-)generating only galleries, the
blog, static pages, etc. To re-generate the entire website, use the option `-c` or `--complete`.

`sbwg -c` or `sbwg --complete`

This command will use the current working directory and put the generated output into the default output directory that is specified in the web site's settings file
(`html/` subdirectory inside the input directory by default). You can define the input and output directories with the options `-i` or `--input` and `-o` or
`--output`:

`sbwg -c -i ~/blog -o /var/www/html`

Note that without the option -v (or --verbose) there will be no output to stdout and no output at all to the terminal if sbwg was successful.

The option `-c` or `--complete` (re-)generates the entire web site (except existing gallery image thumbnails) unconditionally. There are a couple of option that can
speed up the generation process by omitting unchanged parts of the web site or by generating several parts in parallel. See the question "How to speed up the
generation process?" below for information on that.


## How to find entries on the command line?

You can use all tools you would usually use to search text files on a unix-like system. Here are a few examples that might be useful in certain situations.

0. List all entries with the tag "cat:incomplete".
`grep -l cat:incomplete ../../my_weblog/entries/*`
`grep ^cat:incomplete$ /path/to/website/entries/*`

1. List all entries without a defined creation date.
`grep -L '^created:.*$' entries/*`	
	

2. List all stickied posts.
`grep '^sort:[/(stick|about)/].*$' entries/*`	
`grep -Ei '^(sort|created|edited):[A-Z].*' entries/*`


3. List all entries that are sorted specially (independent of their created and edited dates)
`grep -lEi '^(sort|created|edited):[A-Z].*' entries/*`
`grep -l '^sort:.*$' entries/*`


4. List all entries that have been changed in the last 5 days according to the file information (modification date).
`find entries/ -type f -mtime -7 -print`	


5. List all entries that have been edited according to the `edited:` tags inside them.
(tba)


## How to maintain a development/staging website?

You can make use of the `-o` or `--output` option to place the generated web site in a different directory from what is specified in the web site's settings file. If
both the option and the setting are omitted, the script puts the generated web site in the `html` directory inside the source/input directory. A way to maintain
different output directories without having to type them every time is to use aliases.

Example:

`alias sbwg-live='sbwg -o /var/www/html'

`alias sbwg-dev='sbwg -o "${HOME}/weblog_staging"'


## How to change stylesheets and apply changes or create my own CSS?

Create your own style with the name "mystyle" by createing a file named `mystyle.css` in the `styles` directory inside your website source directory. Fill it with
whatever styles you would like applied to all of your generated website, then build the website with the option `-s mystyle`.

For example: `sbwg -c -i /path/to/source/dir -s mystyle`

If you want to create a more complex style, you can split the rules into multiple files. Every file with a name starting with the style name followed by a hyphen
and ending in .css will be used as well. So for example you can split your CSS rules into the files `mystyle.css`, `mystyle-colors.css`, `mystyle-galleries.css`,
`mystyle-whatever.css`. All those files will be linked in every generated HTML page.

For a style for small screens you can hide the navigation bar (the <nav> tag) (or exclude it with a hook) and use a hook to create a link to the file navbar.html to
have the navigation/menu on a separate page.

Of yourse you can copy/rename an existing style and make changes to it so you don't have to start from scratch.


## How to edit an entry without changing its edited date?

This is entirely useless information to current versions of SBWG. It's just not necessary to know or use on SBWG entries anymore. In current and newer versions of
SBWG the edited date is not updated automatically. I'm just leaving this here for now because it's a nice trick in general and I don't know why.

Option 1:
	edit() {> file=$1; mtime=$(stat -c %y "$file"); nano "$file"; touch -d "$mtime" "$file"> }
	edit THE_FILE_YOU_WANT_TO_EDIT
	# Change editor according to your preferance
	# You might want to add this function to your dotfiles ;)

Option 2:
	touch -r ENTRYFILE /tmp/timestamps.tmp
	nano ENTRYFILE
	touch -r /tmp/timestamps.tmp ENTRYFILE
	# Change editor according to your preferances


## How to update the web site after changes without re-generating the entire site?

If you only want to publish the changes in the content of an edited page or entry (no new entry or page needs to be generted and tags have not been changed) then you
can use the options `-p` or `--pages` for pages and `-e` or `--entry` for entries. Using one of these option without an argument will (re-)generate all pages/
entries. Adding the name of an entry/page will only (re-)generate that page/entry.

Examples:

`sbwg -i /path/to/source/dir -e entry_name`
`sbwg -i /path/to/source/dir -e "file name of entry"`
`sbwg -i /path/to/source/dir --entry blog_post_2020-12-24`
`sbwg -i /path/to/source/dir -p "Page Name"`
`sbwg -i /path/to/source/dir --page frontpage`

If other changes have been made to the website source (i.e. changes in tags, new entries or pages), the entire blog needs to be re-generated.

Examples:

`sbwg --complete --input /path/to/source/dir`

or

`sbwg --blog --input /path/to/source/dir`

If you want you could automate this process by regularly executing SBWG so you don't have to run it after every change if it's not important that changes will be
published right away.


## How long does it take to generate a website? Why does it take such a long time?

The time it takes the script to generate a complete web site depends heavily on the amount of content and number of tags like category and topic tags. The more
entries and tagpages have to be generated, the longer it takes of course. The more authors there are in the entries' headers, the more tagpages and combined tagpages
need to be generated. Generating galleries takes the most time, at least when there are new pictures for which no thumbnails have been generated yet.

The other big factor is the environment the script runs in. Available process power, RAM speed and how fast the generated result can be written to the output
directory all play a role. If you think that it takes too long to generate the web site, see the question "How to speed up the generation process?" below. Another
idea is to have a scheduled job (e.g. a cron job) re-creating a web site instead of re-generating it manually every time something has been changed. If changes
don't have to be published right away, you can just leave it up to a daily or hourly job to re-generate the web site in the background. The same is true when you
run SBWG manually though. You don't have to sit and wait until the scribt is done.


## How to share content between otherwise independent web sites?

There are different scenarios how you might want to share content among two web sites.

If you have a weblog with miltiple authors and want to generate a web site that only contains the entries of one of the authors, as an additional web site to the
multi-author site, you can use the `--author` (or `-a`) option.

If you want to share all pages or entries between two web sites you can create a symlink from one `pages/` or `entries/` directory to the other web site's source
directory. By putting some entries in a subdirectory and creating a symlink to it in the entries directory of another web site, you can mirror a subset of the
entries between two sites.

If you want to have some or all entries or pages from a web site mirrored in another web site you can use `ln`, `cp` or `rsync` to link, copy or snyc entries or
pages according to glob patterns. One option to automate this is to save the original files in one web site's source directory and use a hook in the second web
site's settings file to create the copies/links.

Example (use all entries starting with "foo_" from web site also in this web sites):

    hook_entries_start() {
      rm -f "${shellbase}/entries/foo_*"
      cp -s "/path/to/website1/entries/foo_*" "${shellbase}/entries/"
    }


## How to prevent browsers from caching HTML pages too long?

This is best set in the web server configuration, e.g. through the Cache-Control HTTP header. If you're using Apache for example, you can change Cache-Control for a
single web site (or dorectory) with an .htaccess file.


## How to include generic files like robots.txt or .htaccess in the generated HTML site?

Right now something like this has to be done manually. If you want to have a file that is not generated by the script in a directory other than files/ you can put it
there and it will stay there untouched by the script (unless creates a file of the same name of course). Or you can use a hook to copy the file(s) from the
source directory (input directory) to the output directory (the generated web site) to make sure it will be there regardless of the state the output directory was in
before the web site generation started. The hooks 'hook_files' would be a possible choice for this.


## How to change the sizes of images in image galleries (thumbnails, previews, minis)?

The original images are copied to the output directory without being resized. Additionally three sizes of all gallery images are created: preview, thumbnail and
mini. The minis and previews are included on the gallery pages. The thumbnails are placed below a blog entry that has the same name as the gallery. The size of these
resized images can be set in the web site's settingss file by setting the respective variables. If a file under the name of a to be generated image file already
exists, it will not be generated again. This means that, if you want to change the sizes of gallery images that already have been generated with a different size
previously, you have to delete the existing files from the output directory and generate the gallery/galleries again.


## How to check the value of a setting in a web site settings file?

To get the value of a variable that is set in the settings file quickly without printing the entire file, you can search for a line that includes that variable or
source the file and print the value of the variale. Example for the setting 'style':

    grep '^style=*' settings		# This will only work if the variable is set at the beginning of the line.

    (. settings; echo $style )

The brackets are not always necessary. They prevent that any variables or settings in the current shell are changed. Since the file is only sourced in a subshell
any changes made in the file will be lost after the command has finished, which is after the value of the variable has been output to stdout.


## How to speed up the generation process?

Short answer: Use the `-C` (`--cache`) option and delete cache files of things you do want re-generated. The rest of this answer may be ignored. It's more of a
placeholder.

In this version of SBWG the parts of the web site that were requested by action options are by default (re-)generated completely every time. Exceptions are the
various image sizes of gallery images and files in the files/ directory if their modification time hasn't changed. There are plans for improvements in future
versions of SBWG. Any caches created during the generation process is removed when the script is done. There are some ways to change this behaviour or speed up the
generation process by making the script omit certain things.

Use only the action options that you actually need
Actions are those options that tell SBWG which parts of the web site it is supposed to (re-)create. Chances are the weblog is the biggest part of your website that
takes the most time to generate. So if you want to update it completely not much time can be saved. But if you just fixed a typo or added a paragraph to an existing
entry without changing its tags, it's sufficient to only re-generate that entry and all tagpages it appears on. Think about what you changed and what needs to be
updated to know what to re-generate and what to omit in specific cases. For example if you keep menu/navigation in a separate file, not every single page of the web
site needs to be re-generated if you've added an entry with a tag that didn't exist previously.

Use option `-C` or `--cache`
SBWG automatically uses any cache files it encounteres in the cache dir. By default this cache dir is in the temporary directory and thus lost each time SBWG is run.
When the option `-C` or `--cache` is used, the cache dir is in the input directory of the web site. This means that the first time this option is used, persisting
cache files are created. In subsequent runs these cache files are used if the option is supplied again.

Use option `-U` or `--update-only`
This option is not actually implemented, yet. Sorry

Use a RAM disk or fast SSD for your operating systems tmp directory.

Tell the author to improve performance in future versions.

Use a different program because a Bash script may not be what you want if performance is a big concern.

Maybe you don't need it to work any faster
I don't know about anybody else, but I'm fine with the web site updating hours or even days after I've written something. If the changes aren't time sensitive and
it's not a very important mistake that you fixed, you could just wait until a scheduled job re-generates the web site at a later point or you could run the command
and not sit there waiting for it to finish.


## How to run custom code when using SBWG with a specific web site?

There are many possibilities how you can run your own code together with the script. Depending on the use case and you preferences you can choose one over another,
combine multiple of them or think of your own. Of course you can use any method that you can normaly use in your shell (aliases, a wrapper function/script, ...). But
there are a couple of features of SBWG itself that enable customisation.

The `settings` file in the input directory is sourced before the web site is generated. Throughout the web site generation various hook functions are called if they
exist. That way you can write custom code, put it in a hook in the settings file and it will be executed at the applicable location of the script. In the same way
existing functions can be overridden by including them in the settings file.

By using the option `--settings` or `-S` you can pass the script even more commands that will be sourced before the web site is generated but after the settings file
is sourced. That way, options can be added or overridden via the command line option.


## How to modify/customise the script for a certain web site?

SBWG can be customised for different web sites without editing the script itself. The settings file in the input directory can be used to change global variables,
influece the script in many many ways with hooks or even overwrite functions. Since every web site has its own settings file, changes to these settings only affect
that web site. A list of available hooks can be found in the README file. A guide to wrinting hooks or other functions would be a guide to writing code for Bash in
general. Therefore it is not included here. But there are examples for some customisations in this HOWTO file and in the settings file of the example web site.


## How to add additional tags or other code in the HTML header?

Use `hook_head` to inject code into the `<head>` tag of generated HTML files:

    hook_head() {
      [[ -n ${headinsert} ]] && o printf '%s\n' "${headinsert}"		# This adds the value of $headinsert into the HTML header if that variable is not empty.
    }

## How to edit the footer of a web site?

Currently this has to be done by editing the `footer` file of a web site. The file should always contain the following closing tags:

      </body>
    </html>

Before this you can place any additional code that should be included at the end of every HTML page. Here is an example:

        <footer>
         <span id="copr">Copyright © 30 by Jesus of Nazareth</span> - Check out my other web site at <a href="https://example.com/">example.com</a>
        </footer>
      </body>
    </html>


## How to add a side bar or other HTML elements to some or all generated pages?

You can use the hook `hook_navbar_end` to inject additional code after the navbar. For example, to add another navbar you can add this to your web site's settings
file:

    hook_navbar_end() {
      o printf '<nav>\n'
      o printf '<p>This page was generated on '
      o date
      o printf '.</p>\n>
      o printf '<p>This text also will appear on every generated HTML page after the navbar.<p>'
      o printf '</nav>'
    }


## How to add CSS for/change the style of entries with a specific tag differently?

See next answer.


## How to style parts of the web site according to tag values? / How to target tags with colons (:) in CSS?

Escape the colon with a backslash (\).

Examples:

    /* Change the text color of the names of all 'cat:dog' tags below the title of entries */
    .tag.cat\:dog {
      color: violet;
    }

    /* Change the background color of entries with the tag 'cat:penguin' an tagpages (blog view) and on their individual pages */
    div.entry-wrapper.cat\:penguin,
    main.cat\:penguin {
      background-color: coral;
    }

    /* Change how links look in the content of entries written in German (if tagged lang:de) */
    div.entry-wrapper.lang\:de,
    main.lang\:de {
      background-color: coral;
    }


## How to make sure removed content (entries, pages, tags) also get removed from the generated web site?

SBWG does not look at what files and directories already are in the output directory when a web site is generated. Existing files will be overwritten when necessary
but any additional files that may be in the output directory are not touched. I consider this a feature because that way a web site can be complemented with files
from other sources and SBWG does not remove files needlessly. It also means though that if you remove something from the source files of a web site, previously
copied and generated files are not removed by SBWG. This way you may end up with orphaned files in your wen server directory that are not linked from anywhere in the
web site but are still accessible under their URL.

To make sure no such outdated files exist in the output directory, you could remove the entire directory, or everything in it, and generate the website completely
with option -c/--complete. If necessary, this could also be automated by using a hook. This function for example removes everything in the output directory every
time the web site is generated with option -c:

    hook_prepare() {						# Before generating anything
      if option_set c: then					# If the website is being generated with option -c.
        ig option_set_multi v; then local verb=--verbose; fi	# Make rm verbose if SBWG is being run very-verbose.
        rm --recursive --force ${verbose} -- "${odir}/*" \
          && v "Finished emptying the output directory. ✅"	# Remove all content in the output directory.
      fi
    }

But please be aware that this function would also remove the contents of another directory if the web site would be generated into another directory (may be by
accident). Feel free to add safetly mechanisms like hardcoding the directory, using rm's interactive option or requiring the use to press 'y'.
