# NanoBlogger User Manual

## by n1xt3r (Kevin Wood)

The official guide to the NanoBlogger weblog engine.

## 1. Introduction

NanoBlogger is a small weblog engine written in Bash for the command line. It uses common UNIX tools, such as cat, grep and sed to create static HTML content. It's free to use and modify under the GNU General Public License.

Synopsis

    nb [-b blog_dir] [options] <actions> [<keyword> (variable)]

## 2. Features

- flexible command line interface
- highly configurable and script-able :)
- easy drafting, editing and management of entries
- archiving by category, year, month, day, and entry
- pagination
- permanent and navigational links
- templates and CSS style sheets for full control over layout
- placeholders for easy template manipulation
- support for multiple weblogs
- support for multiple categories (tags)
- support for relative and absolute links
- support for date manipulation of entries
- Atom syndication (comes with 1.0 format)
- RSS syndication (comes with RSS 2.0 and 1.0 formats)
- plugins for calendar, recent entries, weblog status, etc.
- plugins for text formatting (e.g. line breaks translate to HTML)
- global (nb.conf) and per-weblog (blog.conf) configuration
- intelligent update system - only updates relative files
- simple cache system for improved efficiency
- independent of java-script and server-side scripting (e.g. PHP)
- independent of external database (stores data in flat-files)
- multi-language support
- multi-platform portability (just Bash and the required commands)

## 3. Requirements

Programs:

Bash (at least v2.05), cat, cp, cut, dirname, date*, grep, mkdir, mv, rm, sed, sort

* = GNU version recommended, but not required

## 4. Getting Started

Creating a New Weblog

To create a new weblog (from your shell prompt):

    nb --blog-dir [myblog_dir] add weblog

where myblog_dir is a nonexistent directory. This will create a new directory, copy the default files over and finally let you edit the weblog's configuration. Multiple weblogs can be created this way.

To set a default weblog directory:

    1. edit either nb.conf or $HOME/.nb.conf.
    2. set BLOG_DIR to your weblog directory:
            BLOG_DIR="$HOME/public_html/[myblog_dir]"

You may also change to the weblog's directory and NanoBlogger will automatically set $BLOG_DIR for you, so you don't have to specify it from the command line.

## 5. Settings and Configuration

To edit the weblog's configuration invoke:

    nb --blog-dir [myblog_dir] configure update all

This opens blog.conf from the weblog directory for editing and updates the entire weblog.

Setting the Browser

NB_BROWSER specifies the browser to use and defaults to the standard BROWSER variable. You can specify a different browser to use by setting NB_BROWSER in blog.conf. In Mac OS X, you might choose to set this to "open". If no browser is specified, "lynx" will be used.

Setting the Editor

NB_EDITOR specifies the editor to use and defaults to the standard EDITOR variable. You can specify a different editor to use by setting NB_EDITOR in blog.conf. If no editor is specified, "vi" will be used.

Setting the Date Format for New Entries

DATE_FORMAT specifies the date format to use for new entries. The default is to use the output from the date command. You can also specify the locale to be used for date command (see the variable DATE_LOCALE). You can specify additional command line arguments with DATE_ARGS, useful for specifying time in UTC. Please note that these settings have no effect on previous entries and that if you use UTC, beware of race conditions which can occur because the entry's filename will be out of sync. The solution is to also change DB_DATEARGS to equal DATE_ARGS, so that the two reflect the same date and time. Read the man pages of the date command to see how to customize the format of the date command's output.

Examples:

    DATE_FORMAT="%m.%d.%Y %H:%M"
    DATE_LOCALE="$LANG"
    DATE_ARGS="-u"

Setting the Timezone

BLOG_TZD sets the timezone for your weblog entries. The default is to set this automatically using, `"%z"`, a non-standard extension of the date command. If the date command on your system doesn't support this, you'll have to set this manually.

Example:

    BLOG_TZD="-0:500"

Setting the Encoding

BLOG_CHARSET sets the character encoding to be used for your weblog.

Example:

    BLOG_CHARSET="iso-8859-1"

WARNING: If you have the Tidy plugin enabled, this setting will be overridden by Tidy. Please, refer to Tidy's documentation for setting the character encoding.

Setting the Mime Type

BLOG_MIMETYPE sets the mime type to be used for your weblog.

Example:

    BLOG_MIMETYPE="text/html"

Setting the Web Address

BLOG_URL should be set as the full URL to your weblog excluding the index file and any preceding "/".

Example:

    BLOG_URL="http://my-site.com/weblog"

Setting the Style Sheet

BLOG_CSS sets the style sheet to be used by your weblog. Style sheets are located in the styles directory.

Example:

    BLOG_CSS="styles/nb_clean.css"

Setting the Favorite Icon

BLOG_ICON sets the favorite icon to be used by your weblog. Favorite icons are located in the images directory.

Example:

    BLOG_ICON="images/favicon.ico"

Toggling display of Directory's Index File in Links

SHOW_INDEXFILE toggles display of a directory index file in links. Defaults to "1", enabled.

Setting the Author's Name

BLOG_AUTHOR can be used to set the author's name, the default is to set the author's name using the common USER variable. Setting BLOG_AUTHOR will override this behavior.

Setting the Default for the "max" Query

MAX_ENTRIES sets the maximum number of entries returned by the "max" query. Defaults to "10".

Setting the Maximum Number of Entries to Display for All Delimited Pages

MAX_PAGE_ENTRIES sets the default maximum number of entries to display for all delimited pages. Defaults to "$MAX_ENTRIES".

MAX_CATPAGE_ENTRIES sets the maximum number of entries to display for each category archive page. Defaults to "$MAX_PAGE_ENTRIES". The category archives will split when the number of entries is greater than $MAX_CATPAGE_ENTRIES.

MAX_MONTHPAGE_ENTRIES sets the maximum number of entries to display for each month archive page. Defaults to "$MAX_PAGE_ENTRIES". The month archives will split when the number of entries is greater than $MAX_MONTHPAGE_ENTRIES.

MAX_MAINPAGE_ENTRIES sets the maximum number of entries to display for each main page. Defaults to "$MAX_PAGE_ENTRIES". The main page will split when $MAX_MAINPAGE_ENTRIES less than the results of MAINPAGE_QUERY.

Setting the Default Query For the Main Page

MAINPAGE_QUERY sets the default query for the main page. Defaults to "max". When combined with MAX_MAINPAGE_ENTRIES, it can be used to paginate the main page.

Setting the Default Text Formatting

ENTRY_FORMAT specifies the default text formatting to use for new entries. Defaults to "raw".

Toggling Creation of Entry Archives

Setting ENTRY_ARCHIVES to equal "1", enables the creation of entry archives and reconfigures the links of the entries to point to their own archive page.

Toggling Creation of Month Archives

Setting MONTH_ARCHIVES to equal "1", enables the creation of month archives.

Toggling Creation of Day Archives

Setting DAY_ARCHIVES to equal "1", enables the creation of day archives and reconfigures the links of the entries to point to their own archive page when $ENTRY_ARCHIVES is not enabled.

Special Archiving Preferences

CATARCH_DATATYPE determines the set of metadata to load for the category archives.

MONTHARCH_DATATYPE determines the set of metadata to load for the month archives.

DAYARCH_DATATYPE determines the set of metadata to load for the day archives.

There's two types of data that can be specified, "ALL" or "NOBODY":

    ALL = full entry metadata (slow and bigger cache)
    NOBODY = all except entry's BODY metadata (faster and smaller cache)

IMPORTANT: Please edit (or create) category_entry.htm, month_entry.htm, and day_entry.htm accordingly.

Setting the Chronological Order

CHRON_ORDER specifies the chronological order of the weblog's archive - 0/1 = normal/reverse. Defaults to "1", reverse order.

WARNING: If you don't use the "configure" action to change this, the databases won't get resorted to reflect the new chronological order.

Setting Actions for Previewing and Publishing

BLOG_PREVIEW_CMD and BLOG_PUBLISH_CMD may both be set to a custom command to run when invoked by their respective actions, preview and publish.

Setting the Cache Preferences

MAX_CACHE_ENTRIES sets the maximum number of entries to store in the cache. Defaults to "$MAX_ENTRIES".

Setting BLOG_CACHEMNG to "0" disables automatic management of the cache. The cache may be managed manually using the `update-cache` command line action.

Toggling Interactive Mode

BLOG_INTERACTIVE toggles interactive mode for your weblog and has the same effect as the `--interactive` command line option. The default is "0" for disabled, setting this to "1" will toggle the mode back on.

Toggling the Display of Time Statistics

SHOW_TIMES toggles showing the accumulated user and system times for the build process. This will probably only prove useful if you don't already have the time command on your system. The default is "0" for off, setting this to "1" will toggle it back on.

Changing the File Type

NB_FILETYPE specifies the file type or rather the suffix for the generated files. The default is set to "html".

Changing the Temp Directory

NB_TEMP_DIR specifies the location to temporarily store data. The default is "/tmp", but may be changed on a per-weblog basis to a more private vicinity as an added security precaution on multi-user systems.

Changing the Default Query Mode

QUERY_MODE specifies the default query mode for all weblog operations. Defaults to "all", but can be just about any valid query. See the "query" action for some possible queries.

Links Configuration

ABSOLUTE_LINKS toggles between absolute and relative links. Defaults to "0", relative links.

FRIENDLY_LINKS toggles between friendly and unfriendly links. Friendly links are more text based, where unfriendly links are more numbers based. Defaults to "1", friendly links.

MAX_TITLEWIDTH sets the maximum title width (by number of characters) generated for friendly links.

SHOW_CATLINKS toggles the display of an entry's categories (tags). The default is to display.

PERMALINKS toggles the display of an entry's permanent link. The default is to display permanent links.

Plugins Configuration

PLUGINS_DIR specifies the directory location of global plugins. Global plugins effect all weblogs. The default is set to $NB_BASE_DIR/plugins.

USR_PLUGINSDIR specifies the directory location of the user plugins. User plugins only effect the specified weblog. Global plugins may be overridden by user plugins on an individual basis. For example, if you copy raw.sh into "$BLOG_DIR/plugins/entry/format/", your copy will be used instead of the global raw.sh. The default is set to $BLOG_DIR/plugins.

Global Configuration

NanoBlogger has it's own configuration file, $NB_BASE_DIR/nb.conf that holds settings which effect all weblogs. The global configuration file is read first meaning that settings in the weblog's configuration may override settings in $NB_BASE_DIR/nb.conf. This configuration is also looked for under the file, $HOME/.nb.conf.

Changing the Default Language of NanoBlogger

NB_LANG is a global configuration variable that sets the language definition to load. The default is "en" for English. All language definitions should be referenced by their ISO 639-2 code.

Example for Spanish:

    NB_LANG="es"

Creating Language Definitions

Creating language definitions is fairly straightforward:

1. start with the default "en" set.
2. redefine all the variables to their equivalent translation in the target language.
3. save the translated set to a sub-directory named after it's ISO 639-2 alpha-3 or alpha-2 code under the "lang" directory.

## 6. Managing Entries and Tags (Categories)

Commands to manage entries and tags.

### Managing Entries

Entry ID's

The latest entry added, will always have an ID of "1", entry's added before that will have ID's of higher values. An entry may have a different ID for each tag view. When modifying entries based on it's tag, ID's for both tag and entry must be specified.

Drafting Entries

Creating a new draft:

    nb [-b blog_dir] draft somefile.txt

Importing the draft as a new entry:

    nb [-b blog_dir] import entry somefile.txt

Creating Entries

Adding new entry:

    nb [-b blog_dir] add entry

Tagging new entry:

    nb [-b blog_dir] --tag <ID> add entry

Setting title and author for new entry:

    nb [-b blog_dir] --title "New Entry" --author [entry_author] add entry

Setting title, author, and body for new entry:

    nb [-b blog_dir] --title "New Entry" --author [entry_author] --text "This is my message." add entry

Importing new entry from file:

    nb [-b blog_dir] import entry somefile.txt

Listing Entries

Listing entries:

    nb [-b blog_dir] list [<query>]

Listing entries by tag:

    nb [-b blog_dir] list tag <ID>

Editing Entries

Editing entry:

    nb [-b blog_dir] edit entry <ID>

Editing entry by tag:

    nb [-b blog_dir] --tag <ID> edit entry <ID>

Editing multiple entries:

    nb [-b blog_dir] edit entry 1,2,3

Assigning Entries To Tags

Assigning tag to entry:

    nb [-b blog_dir] --tag <ID> tag-entry <ID>

Assigning multiple tags to entry:

    nb [-b blog_dir] --tag 1,2,3 tag-entry <ID>

Assigning multiple entries to tag:

    nb [-b blog_dir] --tag <ID> tag-entry 1,2,3

Deleting Entries

Permanently delete entry:

    nb [-b blog_dir] delete entry <ID>

Permanently delete multiple entries:

    nb [-b blog_dir] delete entry 1,2,3

Un-tag entry:

1.) find the entry ID from the listing:

    nb [-b blog_dir] --tag <ID> list

2.) remove the entry using the entry ID we found in the first step:

    nb [-b blog_dir] --tag <ID> delete entry <ID>

Changing Entry's Date

Specifying new entry's date using the TIMESTAMP meta-tag:

    nb [-b blog_dir] --var TIMESTAMP --set-var "CCYY-MM-DD HH:MM:SS" add entry

Changing old entry's date:

    nb [-b blog_dir] --var TIMESTAMP --set-var "CCYY-MM-DD HH:MM:SS" edit entry <ID>

Manually changing entry's date:

    1. nb [-b blog_dir] edit entry <ID>
    2. TIMESTAMP: CCYY-MM-DD HH:MM:SS

The date command must support the "`-d`" option for the date to follow the format set by "`$DATE_FORMAT`".

### Managing Tags

Also known as categories.

Tag ID's

Tag ID's count up from 1. A tag's ID remains constant until that tag is deleted. Deleting a tag will free up that tag's ID for use by a new tag upon creation.

Tag Commands

Creating a new tag:

    nb [-b blog_dir] add tag

Setting the title for a new tag:

    nb [-b blog_dir] --title examples add tag

Listing available tags:

    nb [-b blog_dir] list tags

Tagging existing entries:

    nb [-b blog_dir] --tag <ID> tag-entry <ID>

Editing a tag's title:

    nb [-b blog_dir] --title example edit tag <ID>

Deleting a tag:

    nb [-b blog_dir] delete tag <ID>

### Advanced Management

Use the "--query" option to manipulate the list of entries which to operate from. First review your query by combining the "--query" with the "list" action to see which entry ID(s) matched your query. Then operate from that same query by combining the "--query" option with one of the "edit", "delete", "tag-entry", or "update" actions. Using the entry ID(s) from your last query accordingly.

Editing entries by query:

    nb [-b blog_dir] --query <all,CCYY-MM-DD,max> list
    nb [-b blog_dir] --query <all,CCYY-MM-DD,max> edit entry <ID>

Deleting entries by query:

    nb [-b blog_dir] --query <all,CCYY-MM-DD,max> list
    nb [-b blog_dir] --query <all,CCYY-MM-DD,max> delete entry <ID>

Editing entries by tag and query:

    nb [-b blog_dir] --tag <ID> --query <all,CCYY-MM-DD,max> list
    nb [-b blog_dir] --tag <ID> --query <all,CCYY-MM-DD,max> edit entry <ID>

## 7. Templates

Templates are located in the weblog's sub-directory, templates.

Special Template Characters

IMPORTANT: Escaping these characters is necessary to prevent them from being interpreted by the shell.

Special characters that, when placed in templates, are interpreted by the shell if not escaped:
characters | description | notes
--- | --- | ---
$ | dollar sign | prefix backslash to escape, e.g. "\$"
` | back quote | form of command substitution, prefix backslash to escape, e.g. "\`"
$( | dollar sign and left parenthesis | form of command substitution, prefix backslash to escape, e.g. "\$("

Default Templates

The weblog's appearance is controlled by the following templates:
templates | description
--- | ---
archive_index.htm | controls structure of the archive index page
category_archive.htm | controls structure of the category pages
day_archive.htm | controls structure of the day archive pages
main_index.htm | controls structure of the weblog's main page
main_links.htm* | contains user defined links
makepage.htm | default template used by make-page action
month_archive.htm | controls structure of the month archive pages
permalink.htm | controls structure of the entries' archive pages
entry.htm | controls structure of the entry's content for most archives
permalink_entry.htm | controls structure of the entry's content for individual entry archives
weblog_status.htm | controls structure of weblog status
year_archive.htm | controls structure of year archive pages
entry.metadata | controls the format of the entry's meta-file
file.metadata | controls the format of a meta-file

Special Templates

The weblog's appearance may be further controlled by the following templates:
templates | description
--- | ---
category_entry.htm | controls structure and content of the category entries
month_entry.htm | controls the structure and content of the month entries
day_entry.htm | controls the structure and content of the day entries

## 8. Articles and the Articles Plugin

Articles are independent from the main weblog's archives and they provide a fast and easy way to organize and create additional content for the weblog. Management is almost entirely accomplished through your file manager (or command line). The articles are simply created from meta-files found in the articles directory. Refreshing articles occurs on the next update of the weblog or upon a forced update, whichever occurs first. The generation of the articles listing and content depends on the articles plugin. For more information about the articles plugin, please refer to "*articles_meta.sh" in About Plugins.

### Configuring Articles

Setting the Articles Directory

ARTICLES_DIR sets the articles directory for your weblog. Defaults to "articles". Multiple articles directories may be specified.

Example:

    ARTICLES_DIR="articles articles/misc"

Setting the Default Text Formatting for Articles

ARTICLES_FORMAT sets the default text formatting for new articles. Defaults to "raw".

Setting the Default Suffix for Articles

ARTICLES_SUFFIX sets the suffix to include as article under the articles directory. Defaults to ".txt".

Setting the Default Template for Articles

ARTICLES_TEMPLATE sets the default template to use for new articles. Defaults to "[blog_dir/]templates/makepage.htm".

### Adding New Articles

Creating new articles is made easy with help from the 'add article' command:

    nb [--title 'Example Article'] add article

Importing new article (into existing articles sub-directory):

    nb import article [blog_dir/]articles/misc/example.txt

Manually Refreshing Articles

Manually refreshing articles listing and content:

    nb update articles

## 9. About Plugins

### Plugins Framework

Regular Plugins: plugins

Regular plugins are initialized unconditionally after a requested update.

Archive Plugins: plugins/archive

Archive plugins are initialized when the archives are to be updated.

Category Archive Plugins: plugins/archive/category

Category Archive plugins are initialized for each category archive that is to be updated.

Day Archive Plugins: plugins/archive/day

Day Archive plugins are initialized for each day archive that is to be updated.

Month Archive Plugins: plugins/archive/month

Month Archive plugins are initialized for each month archive that is to be updated.

Year Archive Plugins: plugins/archive/year

Year Archive plugins are initialized for each year archive that is to be updated.

Entry Plugins: plugins/entry

Entry plugins are initialized unconditionally for each entry that is to be updated.

Entry Modify Plugins: plugins/entry/mod

Entry Modify plugins are initialized for each entry that is modified.

Entry Formatting Plugins: plugins/entry/format

Entry Formatting plugins are initialized for each modified entry based on the FORMAT meta-tag field. More than one format may be specified using space or commas as a separator, but special care should be taken in the order they get specified.

Page Plugins: plugins/page

Page plugins are initialized unconditionally before each page that is to be updated.

Page Formatting Plugins: plugins/page/format

Page Formatting plugins are initialized for each page that is to be updated based on the FORMAT meta-tag field. More than one format may be specified using space or commas as a separator, but special care should be taken in the order they get specified.

Make Page Plugins: plugins/makepage

Make Page plugins are initialized after each page that is to be updated.

Post Plugins: plugins/post

Post plugins are initialized unconditionally for post-weblog related tasks.

Note: Most plugins will operate on their own conditions once they've been initialized, in other words, no longer unconditionally.

Default Plugins

Default plugins (most are enabled by default):
plugins | description | variables | targets | notes
--- | --- | --- | --- | ---
archive/day/cal2daytitle.sh | creates a fancier title for the day archives | CAL_CMD, CAL_ARGS, DATE_LOCALE | $NB_ArchiveTitle | requires the cal command
archive/month/month_calendar.sh | generates a calendar with links for each active day | CAL_CMD, CAL_ARGS, DATE_LOCALE | $NB_MonthlyCalendar | requires the cal command
archives/year/year_index.sh | generates year archives | none | $ARCHIVES_DIR/$yearn/index.$NB_FILETYPE | requires makepage.htm template
articles_meta.sh* | generates articles from meta-files in the "articles" directory | ARTICLES_DIR, ARTICLES_FORMAT | $NB_ArticleLinks | requires makepage.htm template, plugin should be ordered so that it's loaded last
atom.sh | adds atom feed | BLOG_FEED_ITEMS, ATOM_ITEMS, ATOM_CATFEEDS, ATOM_FEED_LANG | $NB_AtomVer, $NB_AtomFile, index-atom.$NB_SYND_FILETYPE | none
calendar.sh | generates a calendar with links for each active day | CAL_CMD, CAL_ARGS, DATE_LOCALE | $NB_Calendar | requires cal
entry/category_links.sh | generates category links | none | $NB_EntryCategories | none
entry/excerpt.sh* | creates excerpt from entry's text | none | $NB_EntryExcerpt | ends after first detected double line break (blank line)
entry/format/autotag-br.sh | converts blank lines to HTML paragraph breaks | none | $NB_MetaBody, $NB_EntryBody | FORMAT: autotag-br
entry/format/markdown.sh | uses markdown to handle formatting | MARKDOWN_CMD, MARKDOWN_OPTS | $NB_MetaBody, $NB_EntryBody | FORMAT: markdown
entry/mod/base_url.sh | helps set relative links | %base_url% | $NB_EntryBody | example: <img src="%base_url%images/pic.png" />
entry/mod/moods.sh | converts mood variables into smiley icons | MOODS_URL | $NB_EntryBody | copy moods directory to weblog's directory
fortune.sh | generates random quotes | FORTUNE_CMD, FORTUNE_FILE | $NB_Fortune | requires fortune
makepage/tidy.sh | validates HTML/XML code | TIDY_CMD, TIDY_HTML_ARGS, TIDY_XML_ARGS | $NB_Tidy, $BLOG_DIR/tidy.log | requires HTML Tidy, overrides $BLOG_CHARSET
mymood.sh* | adds ability to display your mood | MOODS_URL | $NB_MyMood | copy moods directory to weblog's directory
page/feed_links.sh | generates alt links for feeds | none | $NB_AtomAltLink, $NB_RSS2AltLink, $NB_RSSAltLink | requires one of atom.sh, rss.sh, or rss2.sh plugins
page/page_links.sh | regenerates links for inclusion on other pages | none | $NB_MainLinks, $NB_RecentEntries, $NB_CategoryLinks, $NB_MonthLinks, etc. | requires one of weblog_links.sh or recent_entries.sh plugins
page/format/autotag-br.sh | converts blank lines to HTML paragraph breaks | none | $NB_MetaBody, $NB_EntryBody | FORMAT: autotag-br
page/format/markdown.sh | uses markdown to handle formatting | MARKDOWN_CMD, MARKDOWN_OPTS | $NB_MetaBody, $NB_EntryBody | FORMAT: markdown
page/format/moods.sh | converts mood variables into smiley icons | MOODS_URL | $NB_MetaBody, $NB_EntryBody | may combine with with others e.g. "FORMAT: moods, markdown"
recent_entries.sh | generates lists of recent and old entries | RECENTLIST_ENTRIES, RECENTLIST_OFFSET, RECENTLIST_MODE | $NB_RecentEntries, $NB_OlderEntries | none
rss2.sh | adds rss 2.0 feeds | BLOG_FEED_ITEMS, RSS2_ITEMS, RSS2_CATFEEDS, BLOG_FEED_LANG | $NB_RSS2File, index-rss.$NB_SYND_FILETYPE | none
rss.sh | adds rss 1.0 feeds | BLOG_FEED_ITEMS, RSS_ITEMS, RSS_CATFEEDS, BLOG_FEED_LANG | $NB_RSSFile, index.$NB_SYND_FILETYPE | none
weblog_links.sh | generates some useful links | ALL_YEARLINKS, MAX_YEARLINKS, ALL_MONTHLINKS, MAX_MONTHLINKS | $NB_MainLinks, $NB_MonthLinks, $NB_CategoryLinks | requires main_links.htm template
weblog_status.sh | generates some statistics | none | $NB_BlogStatus | requires weblog_status.htm template

* = actual name may vary.

To disable an individual plugin, rename the plugin's extension from ".sh" to ".off".

## 10. Configuring Plugins

Settings for plugins are stored and set in your weblog's blog.conf.

### Configuring Syndication Plugins

Syndicating your weblog is achieved through NanoBlogger's plugins. Please note, a complete and Internet accessible URL is required for proper syndication. This can be set using BLOG_FEED_URL. It is also wise to ensure a correct timezone setting for your syndication feeds. For this, please refer to BLOG_TZD in Settings and Configuration.

Setting the Web Address

BLOG_FEED_URL sets the URL for syndication feeds. Defaults to "$BLOG_URL", only if it's already set.

Example:

    BLOG_FEED_URL="http://www.example.com/johndoe/weblog"

Setting the Time Zone

BLOG_FEED_TZD sets the timezone used for syndication feeds. Defaults to "$BLOG_TZD".

Setting the Lanuage

BLOG_FEED_LANG sets the language used in your syndication feeds.

Example:

    BLOG_FEED_LANG="en-us"

ATOM_FEED_LANG sets the language for Atom syndication feeds.

Example:

    ATOM_FEED_LANG="en"

NOTE: The language code for Atom syndication feeds is different from the RSS standard.

Setting the Maximum Number of Items to Syndicate

BLOG_FEED_ITEMS sets the maximum number of entries to include in your syndication feeds, independent of $MAX_ENTRIES. Defaults to "10". For exporting purposes you may want to set this to "-1" to include all the existing weblog's entries.

Example:

    BLOG_FEED_ITEMS="10"

Support for Style Sheets

BLOG_FEED_CSS sets the style sheet used for your syndication feeds (path should be relative).

Example:

    BLOG_FEED_CSS="styles/feed.css"

Support for Icons & Logos

BLOG_FEED_ICON sets an icon for your syndication feeds (path should be relative).

Example:

    BLOG_FEED_ICON="images/feedicon.png"

BLOG_FEED_LOGO sets a logo for your syndication feeds (path should be relative).

Example:

    BLOG_FEED_LOGO="images/feedlogo.png"

NOTE: In the RSS 2.0 syndication plugin, the logo will be used when the icon is not set.

Support for Syndicated Categories

There are three settings that control category syndication feeds:

1. CATEGORY_FEEDS master toggle for category syndication. Defaults to "0" - disabled.
2. ATOM_CATFEEDS toggles Atom based syndication for categories. Defaults to "0" - disabled.
3. RSS2_CATFEEDS toggles RSS 2.0 based syndication for categories. Defaults to "0" - disabled.

Support for Creating Podcasts

There's a special meta-tag called, ENCLOSURE which is used to set an entry's enclosure data for each entry. The ENCLOSURE meta-tag should contain two different sets of data separated by a single space. The local media file and the media type (e.g. audio/mpeg).

Example:

    ENCLOSURE: mp3s/mypodcast.mp3 audio/mpeg

The media file should be from a relative path which can be found from within $BLOG_DIR. The system command "du -b" is required to acquire the media file's length to complete the enclosure data. The "du" command should be included on most systems where Bash is supported, but there's no guarantee the syntax will be the same. Auto-detecting the media type is not supported, it must be determined and set manually. Enclosures are supported for both the Atom and RSS2 syndication plugins.

### Syntax Checking & Reformatting

The Tidy plugin provides syntax checking and reformatting. These kind of tools can be both your friend and your enemy, meaning they can sometimes hide (fix) your mistakes too well. A log is kept in your weblog's directory, so you can review any errors or changes recorded by Tidy.

There are two Tidy configuration variables. One for HTML and one for XML (syndication plugins). As noted in Settings and Configuration, Tidy has a tendency to rewrite whatever you set in $BLOG_CHARSET. So beware.

TIDY_HTML_ARGS sets the command arguments for the tidy command.

TIDY_XML_ARGS set the command arguments for the tidy command when verifying XML of syndication feeds.

Examples:

    TIDY_HTML_ARGS="-asxhtml -n -utf8"
    TIDY_XML_ARGS="-xml -n -utf8 -wrap 0"

More advanced configuration including customizations can be achieved through user plugins.

## 11. Writing Plugins

### Tools for Developing Plugins

Plugins typically work by creating placeholders for the templates, but are in no way limited to creating placeholders. Placeholders allow for a great deal of control in how the plugins output is placed in the template. Some plugins may require you to identify it's unique placeholder/destination and manually add it to your templates.

To write a plugin, you should begin by creating a text file with the ".sh" suffix. plugins are basically shell scripts that get loaded (sourced in shell terms) depending on where the plugin is located in the plugins directory or one of the plugin sub-directories. It may be a good idea to look at a simple plugin, such as fortune.sh for an idea on how a plugin works. When the new plugin is saved, it needs to have the appropriate read permissions, so it can be loaded by NanoBlogger. Executable permissions are not necessary for plugins.

The following is a collection of tools that might be useful when developing your own plugins.

Plugin API

API for writing plugins.
command | description | variables and switches | targets | notes
--- | --- | --- | --- | ---
die | exits with error message | $@ | stdout | returns exit status 1
nb_browser | sensible-browser-like utility for launching browser | $NB_BROWSER, $BROWSER, $1 | stdout | parses $BROWSER with ":" separator
nb_edit | simple wrapper to editor | $NB_EDITOR, $EDITOR, $1, $2, -p = force prompt (pause) | stdout | if $2 is null, then $1 assumed to be file
nb_eval | silent wrapper to eval | $? | $DEVNULL | returns exit status 0 upon success
nb_print | prints a file line by line | filename=$1, number of lines=$2 (blank for all) | stdout | use instead of "sed 1q"
nb_msg | preferred method of verbosity | $@ | stdout | use instead of echo when appropriate
confirm_action | ask user to confirm action | none | stdout | can be used with $BLOG_INTERACTIVE
chg_suffix | changes a file's suffix | filename=$1, suffix=$2 | file | can specify $NB_FILETYPE, $NB_SYND_FILETYPE as suffix
query_db | queries database | db_query=$1, db_catquery=$2, db_setlimit=$3 db_limit=$4, db_offset=$5 | $DB_RESULTS | example (retrieves entries 1 through 10): "query_db all nocat limit 10 1"
lookup_id | lookup id of item matched from master database | $1, $2 | stdout | example: lookup_id 2005-12-14T00_00_00.$NB_DATATYPE "$MASTER_DB_RESULTS"
translit_text | transliterates text into a suitable form for web links | $1 | stdout | none
set_baseurl | helps in setting relative links | node_var=$1, base_dir=$2 | $BASE_URL, $ARCHIVES_PATH | should only specify one, of node_var or base_dir, at a time
set_catlink | sets link and file for given category | $1 | $category_file, $category_link | category should be of the form, cat_N.$NB_DBTYPE
set_daylink | sets link and file for given day | $1 | $day_file, $day_link | day should be of the form CCYY-MM-DD
set_monthlink | sets link and file for given month | $1 | $month_file, $month_link | month should be of the form CCYY-MM
set_entryid | sets anchor/id for given entry | $1 | stdout | entry should be of the form CCYY-MM-DDTHH_MM_SS.$NB_DATATYPE
set_entrylink | sets link and file for given entry | $1 | $entry_dir, $permalink_file, $NB_EntryPermalink | entry should be of the form CCYY-MM-DDTHH_MM_SS.$NB_DATATYPE
update_cache | compiles list or removes cache entries | cache_update=$1, cache_def=$2, CACHEUPDATE_LIST=$3 | $CACHE_LIST | commonly used to expire cached data
load_template | loads template from file | TEMPLATE_FILE=$1 | $TEMPLATE_DATA | never load template data more than once, make_page calls load_template
write_template | writes template data to stdout | $TEMPLATE_DATA | stdout | example: write_template > "$OUTFILE"
load_metadata | loads metadata from (entry) file | METADATA_TYPE=$1, $METADATA_FILE=$2 | depends on $METADATA_TYPE | metadata type can be ALL, NOBODY, BODY, TITLE, AUTHOR, DATE, DESC, FORMAT
write_metadata | writes metadata to file | MVAR=$1, METADATA=$2, META_FILE=$3 | $META_FILE | example: "write_metadata UPDATED "`date`" $meta-file"
read_metadata | extracts metadata from (entry) file | MVAR=$1, META_FILE=$2 | $METADATA | see plugin recent_entries.sh for a good example
write_var | create/modify user metedata field | WRITE_MVAR=$1, WRITE_MVARVALUE=$2, WRITEMETAVAR_FILE=$3 | $WRITEMETAVAR_FILE | example: write_var MODTIME "$(date)" $meta-file
loop_archive | loops through archives and executes instructions by years or months | looparch_list=$1, looparch_type=$2, looparch_exec=$3 | determined by $looparch_exec | example: "query_db max; loop_archive "$DB_RESULTS" months make_monthlink"
load_entry | loads entry data for templates | ENTRY_FILE=$1, ENTRY_DATATYPE=$2, ENTRY_CACHETYPE=$3 | $NB_EntryTitle, $NB_EntryBody, ... | see plugin atom.sh for a good example
make_page | creates weblog page from text file | MKPAGE_SRCFILE=$1, MKPAGE_TMPLFILE=$2, MKPAGE_OUTFILE=$3 | $MKPAGE_CONTENT, $NB_MetaBody | see plugin articles_text.sh for a good example
weblog_page | creates weblog page from meta-file | BLOGPAGE_SRCFILE=$1, BLOGPAGE_TEMPLATE=$2, $BLOGPAGE_OUTFILE=$3 | $MKPAGE_CONTENT, $NB_MetaBody | see plugin articles_meta.sh for good example

## 12. Publishing

Setting the Publish Command

The BLOG_PUBLISH_CMD variable allows you to set a command to publish your weblog. This can be as simple as an FTP command to upload files or a more complex set of tasks via a script.

Publishing Remotely

FTP, SSH (scp, sftp, etc.), RSYNC or WebDAV, are all methods that can be used to publish the weblog.

example: automating publishing with ftp and .netrc.

blog.conf:

    BLOG_PUBLISH_CMD="ftp example.weblog.com"

.netrc:

    machine example.weblog.com login foo password
    RIGHT!
    macdef init
    passive on
    prompt off
    lcd ~/public_html/blog
    mput *.*
    cd archives
    lcd archives
    mput *

Publishing Locally

If you choose to publish locally, you'll probably want to disable the publish command. To do this you can set BLOG_PUBLISH_CMD to null. e.g. BLOG_PUBLISH_CMD=""

## 13. Adding Support for Comments

Comment services and add-on's: NanoBlogger Comments, CGIComment, blogkomm[1], JS-Kit[2], and Haloscan.com[3].

Choose one and follow the included install instructions.

## 14. Importing Entries

In order to import entries, data must first be converted to the NanoBlogger format.

Format of an Entry

An entry file name is of the format:

    CCYY-MM-DDTHH_MM_SS.txt

So a typical entry's file name would look something like this:

    2004-06-25T22_24_37.txt

The format of an entry is made up of meta-tags . Most of the meta-tags are of the format VAR: VALUE, then a carriage return that separates one meta-tag from the next. The order of the meta-tags are insignificant. The BODY variable is special and needs to be terminated by the END----- marker. By default the content of the BODY variable must contain valid HTML with all entities properly escaped.

Example of an entry's format:

    TITLE: A New Entry
    AUTHOR: foo
    DATE: January 30 2004, 12:00 PM
    DESC: keywords or a short, one line summary
    FORMAT: raw
    -----
    BODY:
    <p>This is my new entry ...</p>
    END-----

Converting Entries

Before entries can be imported they must be converted to the correct format.

Steps to converting entries:

    1. Convert each entry so they each contain the following meta-tags: TITLE, AUTHOR, DATE, DESC, FORMAT, BODY
    2. The BODY meta-tag must be terminated by "END-----".
    3. Rename each entry's file name to it's corresponding date and time.

If there's multiple entries it may be a good idea to automate all this with a script.

Updating the Weblog's Data Directory

The imported entries should be copied into the data directory of your weblog.
Update the weblog with the new entries:

    nb [-b blog_dir] --force update all

## 14. Tips and Tricks

Useful Editor's Commands

Create a new meta-file:

    nb [-b blogdir] make-file somefile.txt

Import the meta-file as a new weblog entry:

    nb [-b blogdir] import entry somefile.txt

or export the meta-file as a new weblog page:

    nb [-b blogdir] make-page somefile.txt somefile.html

Please note that these tasks are easier when the editor supports a sub-shell or when you can suspend your editor from the active shell (assuming there is one).

Writing Meta Tags on the Fly

Meta-tags are simply the tags that pertain to a meta-file. For instance, the text formatting can be manipulated from the command line.

    nb [-b blogdir] --var FORMAT --set-var "markdown" make-page somefile.txt somefile.html

Currently, only one meta-tag may be specified at a time.

Set a Default Weblog Directory

By default you have to specify the weblog directory, but by setting BLOG_DIR, you won't have to. Edit nb.conf or $HOME/.nb.conf:

    BLOG_DIR="/path/to/weblog"

Disabling Plugins

You may wish to disable the global plugins or all plugins.

To disable global plugins edit blog.conf and change PLUGINS_DIR to a preexisting directory:

    PLUGINS_DIR="$BLOG_DIR/plugins"

To disable all plugins, including user's, edit blog.conf and change PLUGINS_DIR and USR_PLUGINSDIR to a preexisting (empty) directory:

    PLUGINS_DIR="$BLOG_DIR/no-plugins"
    USR_PLUGINSDIR="$BLOG_DIR/no-plugins"

As noted previously, plugins can be disabled on an individual basis by changing their suffix to something other than ".sh".

Adding Shell Scripting to Your Templates

It's possible to use command substitution in your templates, using one of the following forms:

            $(command)
    or
            `command`

Add an Introduction to Your Weblog

Create a text file in your weblog directory called, "intro.txt". Edit the text file the way you like, then add the following to the main template:

    $(< "$BLOG_DIR/intro.txt")

Integrating Parts of Your Weblog Into an Existing Web Site

Many parts of the weblog are stored and built in the parts directory. Say you already have a web site full of your own custom server-side scripts/includes, but you'd like to add a news section. This is where the "parts/index.html" file comes in. It contains all the most recent entries, so adding a news/diary/blog section is just a matter of adding the code to include "parts/index.html" into the page.

Other clever uses include combining NanoBlogger's static output with some PHP or Perl. For example, suppose you like to have some of the side links, such as recent entries. Using PHP, set your NB_FILETYPE to "php" and modify the appropriate templates to include the PHP code that extracts the data from the parts directory. One of the main advantages to this is not having to rebuild the entire weblog's archives, just to keep the links current.

Embedding Other Variables in the Templates

Any characters that are similar to the shell's variable or command substitution characters, will have to be escaped before they will work from the templates.

Example using variables in the PHP code:

    <?php
    \$VAR = array ();
    echo "\\\$VAR=\$VAR";
    php?>

## 16. Credits

Thanks to Adrien "ze" Urban, Paul Drain, Pavel Janik, and O.R.Senthil Kumaran for all the contributions and suggestions. Thanks to Bowie J. Poag, author of MicroBlogger, for the inspiration of this project. Special acknowledgment goes to Ted Walther's Diary[4], which inspired Bowie to create MicroBlogger. Finally, thanks to everyone who's ever contributed a patch or feature request - see the ChangeLog.

1. http://blogkomm.com
2. http://js-kit.com
3. http://www.haloscan.com
4. http://reactor-core.org/~djw/diary/

Copyright © 2003-2008 Kevin Wood. All Rights Reserved.