This is a read-only repository mirror for dblg, a [simple] dynamic blogging utility. dblg is a small, no-nonsense web application supporting the bare minimum required for publishing blog (or "micro-blog") content.
I run it on Mac OS X and OpenBSD (with pledge(2) support).
It has three components:
-
A back-end server. This is a tiny CGI script written in C, dblg.c. It links to kcgi and ksql, and uses SQLite for its backing store. It produces JSON objects, an Atom feed, or static HTML5 so it can be driven by any front-end conforming to its expectations.
-
An editing front-end, dblg.xml, dblg.css, and dblg.js. This part drives the back-end by providing an interface for saving entries, publishing them, and doing user management. The editor front-end is usually installed on the same machine as the back-end, but that's really just a matter of convenience of keeping both in sync. You can build your own editor front-end that drives the back-end server---it's just JSON and HTML forms---but that's kind of a PITA.
-
A blog viewer front-end, blog.js and, for reference, blog.xml, blog.css. Your public-facing pages will want to be filled in with blog content, which they can do by including the JavaScript file blog.js and having an HTML element with identifier
blog
filled-in as in the reference. Your page will then invoke the script when desired. A static version of blog front-end, blog-static.xml, is provided (though it must be configured by the administrator) to have static blog content. The latter is required if you want your blog spidered. I use both: one for "blog" front matter and the other for permanent-link articles.
This tool is still under development, as is its documentation. For a view of it working, see my diving blog.
The project is being tracked by Coverity for static analysis of the C source code.
Some features:
- Simple, easy-to-audit code.
- Straightforward user administration (admins, regular users).
- Publish directly or delay publication and edit privately.
- Support for cloud-based images, for now limited to Cloudinary (which I use for the divelog).
- Geolocation and coordinates attached to each entry (or suppressed).
- Supports language tags.
- Responsive layout for small displays.
- Strong HTTP caching with etags, full compression support.
- Security: cookies with security extensions and full support for CSP (no in-line JavaScript)
- Atom feed support.
- Static HTML support.
The default editor front-end uses moment.js for formatting dates, clipboard.js for copying to the clipboard (apparently this is hard?), and js-sha1 for SHA1 hashing the cloud authorisation.
The default viewer optionally (but strongly recommended) uses moment.js and showdown for formatting MarkDown. The default static page also uses showdown.
Beyond this document, you can also view the database schema or the RESTful API.
As mentioned, there are three components to this blogger: the back-end, the editor, and the viewer. The back-end and editor usually go in the same place, so I'll start with them.
You'll first need to download and configure the software. This is fairly straightforward. First, download. Then, open the GNUmakefile. Override the variables you'd like in a GNUmakefile.local file (which won't be touched). The GNUmakefile documents each variable and has an example deployment on a default OpenBSD machine.
You'll need kcgi and ksql for the back-end server.
Once configured, run make installcgi
for first-time to install the
database and the CGI script; else, make updatecgi
only to freshen the
CGI script and not touch the database.
If you're upgrading from an old version of dblg (i.e., with make updatecgi
and differnt versions), the database may have changed. Each
version with a changing upgrade has a database upgrade script as
dblg-OLD-NEW.sql. Run those in order.
To install the editor tools, use make installserver
. This will only
install the HTML, JavaScript, and CSS for the editor.
There are two ways of "viewing" blog content. The first is to dynamically load using JSON; the second, static HTML.
To install the viewer, you don't need to download this software. Simply reference the existing blog.xml and blog.css, then include blog.js files in your application.
<script src="//cdn.rawgit.com/kristapsdz/dblg/master/blog.js"></script>
<script>
window.addEventListener('load', function(){
blogclient('/cgi-bin/dblg', {
blog: '/blog.html',
editor: '/dblg.html',
limit: 5
});
});
</script>
In this invocation, the script is pulled from GitHub's CDN and invoked
in an embedded HTML script. The embedded script calls the blogclient
function, passing it some example values. The blogclient
function
consists of two arguments:
blogclient(url, options);
The url
argument is the URL of the blog CGI script. The options
dictionary is optional and may consist of any or all of the following
optional values:
blog
: the URL for the blog pageeditor
: string pointing to the editor URL (no editor, if null)entryid
: an integer that's the unique identifier of a specific entry to pull down (if unspecified, this is checked in the query string)lang
: a string limiting the languages of pulled articleslimit
: an integer limiting the number of pulled articles (else all)order
: a string of eitherctime
ormtime
being the default sort order of pulled articlespostload
: a function that is invoked after all processing has been done after successfully downloading and parsing the resultsrescroll
: a Boolean indicating that if there's a document hash, re-scroll to that hash after loading the page (and beforepostload
)
The blogclient
function asynchronously manipulates the DOM tree within
and including the blog
identifier, the root element that (obviously)
should be included somewhere in the calling page. When blogclient
is
invoked, it synchronously adds the hide
attribute to the root element
before starting asynchronously downloading blog content.
Upon success, the child of this element is removed, cloned, and replicated for each blog element shown on the page.
<div id="blog">
<div>
<!-- This is duplicated and filled in for each entry. -->
<!-- Node manipulation happens over "class" attributes. -->
</div>
</div>
Within the root element, the following classes have their contents
replaced by content. Note that calendar form refers to using
moment.js's calendar()
function, if found, or
simply a generic date string otherwise. Note also that markdown
refers to HTML-ised markdown if
showdown is loaded, or the raw
markdown otherwise.
blog-ctime
: calendar form of entry creation timeblog-mtime
: calendar form of entry update time, which is initialised to entry creation timeblog-author
: name of blog entry authorblog-title
: title of blog entryblog-aside
: article synopsis markdown contentblog-content
: article content markdown content
Furthermore, the following element attributes are set or unset.
blog-author-link
: if provided,href
is set to the author's link; otherwise, thehref
attribute is removedblog-canon-link
: if ablog
argument is provided to theblogclient
configuration object,href
is set to that and the?entryid=nnn
parameter; otherwise, thehref
attribute is removedblog-coords
: if coordinates are provided, setshref
to a Google maps link (in satellite mode) of the coordinates; otherwise, thehref
is removedblog-fb-link
: if theblog
argument is provided to theblogclient
configuration object,data-href
is set to the canonical blog link anddata-numposts
also set; otherwise, they are removedblog-image
: if provided,src
is set to the image link; otherwise, thesrc
attribute is removedblog-image-link
: if provided,href
is set to the image link; otherwise, thehref
attribute is removed
The following have the hide
attribute ("hidden") set on the containing
element given the noted conditions.
blog-canon-box
: hidden if ablog
argument is not provided to theblogclient
configuration objectblog-coords-box
: hidden if there are no coordinatesblog-ctime-box
: hidden if there is a modification timeblog-image-box
: hidden if there is no imageblog-mtime-box
: hidden if there is not a modification time
After filling in these fields for each blog entry, the hide
class is
removed from the root element.
Static content is full-formed HTML5 produced by the back-end. To use this mode, which is not enabled by default, you'll need to enter the administration page and provide a template that will be filled in by the back-end and passed to the front-end. A sample is provided in blog-static.xml. This is not installed by default: you'll need to copy it into your web root and point to it in the administrative console.
The following template keys are populated:
dblg-aside
: aside content (Markdown)dblg-author-link
: link to author, if given (otherwise blank)dblg-author-name
: author namedblg-canon
: canonical link to blog entrydblg-canon-query
: blog entry query stringdblg-classes
: a string consisting of zero or moreauthor-has-link
,blog-has-aside
,blog-has-image
,blog-has-image-aside
,blog-has-only-aside
,blog-has-only-image
,blog-has-only-ctime
,blog-has-mtime
,blog-has-coords
(explanation fairly self explanatory)dblg-content
: content (Markdown)dblg-coord-lat-decimal
: latitude decimal (if coordinates given, else empty)dblg-coord-lng-decimal
: longitude decimal (if coordinates given, else empty)dblg-ctime
: epoch date of creation timedblg-ctime-iso8601
: ISO 8601 formatted creation timedblg-image
: blog image (if given)dblg-mtime
: epoch date modification time (starting with creation time)dblg-mtime-iso8601
: ISO 8601 formatted modification timedblg-title
: entry title (not Markdown)
All sources use the ISC (like OpenBSD) license. See the LICENSE.md file for details.