├── .github └── workflows │ └── makefile.yml ├── .gitignore ├── LICENSE.md ├── Makefile ├── README.md ├── archive.xml ├── article.c ├── article.css ├── article.xml ├── article1.xml ├── article10.md ├── article2.xml ├── article4.xml ├── article5.xml ├── article6.xml ├── article7.xml ├── article8.xml ├── article9.xml ├── atom-template.xml ├── atom.c ├── compats.c ├── compile.c ├── configure ├── coverage.xml ├── example1-article.xml ├── example1-template.xml ├── example2-article1.xml ├── example2-article2.xml ├── example2-template.xml ├── example3-template.xml ├── examples ├── brutalist │ ├── Makefile │ ├── README.md │ ├── article1.md │ ├── article10.md │ ├── article2.md │ ├── article3.md │ ├── article4.md │ ├── article5.md │ ├── article6.md │ ├── article7.md │ ├── article8.md │ ├── article9.md │ ├── atom-template.xml │ ├── index.css │ ├── index.xml │ ├── template.css │ └── template.xml ├── photos-column │ ├── Makefile │ ├── README.md │ ├── atom-template.xml │ ├── index.css │ ├── index.xml │ ├── photo.css │ ├── photo.xml │ ├── photo1.jpg │ ├── photo2.jpg │ ├── photo3.jpg │ ├── photo4.jpg │ ├── photo5.jpg │ ├── photo6.jpg │ ├── photo7.jpg │ └── photo8.jpg ├── photos-grid │ ├── Makefile │ ├── README.md │ ├── atom-template.xml │ ├── index.css │ ├── index.xml │ ├── photo.css │ ├── photo.xml │ ├── photo1.jpg │ ├── photo2.jpg │ ├── photo3.jpg │ ├── photo4.jpg │ ├── photo5.jpg │ ├── photo6.jpg │ ├── photo7.jpg │ └── photo8.jpg ├── retro │ ├── Makefile │ ├── README.md │ ├── article1.md │ ├── article2.md │ ├── atom-template.xml │ ├── index.css │ ├── index.xml │ ├── template.css │ └── template.xml ├── simple-frontpage │ ├── Makefile │ ├── README.md │ ├── article1.xml │ ├── article2.jpg │ ├── article2.xml │ ├── article3.jpg │ ├── article3.xml │ ├── atom-template.xml │ ├── index.css │ ├── index.xml │ ├── template.css │ └── template.xml └── simple │ ├── Makefile │ ├── README.md │ ├── article1.xml │ ├── article2.xml │ ├── article3.xml │ ├── atom-template.xml │ ├── profile1.jpg │ ├── profile2.jpg │ ├── template.css │ └── template.xml ├── extern.h ├── grok.c ├── index.css ├── index.d.ts ├── index.xml ├── index1.dot ├── index2.dot ├── index3.dot ├── index4.dot ├── json.c ├── linkall.c ├── listtags.c ├── main.c ├── notugly.xsl ├── package.json ├── regress ├── blog │ ├── article-from-attr.html │ ├── article-from-attr.in.xml │ ├── article-from-attr.template.xml │ ├── article-from-attr2.html │ ├── article-from-attr2.in.xml │ ├── article-only-tags.html │ ├── article-only-tags.in.xml │ ├── article-only-tags.template.xml │ ├── entities.html │ ├── entities.in.xml │ ├── entities.template.xml │ ├── nav-from-attr.html │ ├── nav-from-attr.in.xml │ ├── nav-from-attr.template.xml │ ├── nav-only-tags.html │ ├── nav-only-tags.in.xml │ ├── nav-only-tags.template.xml │ ├── navcontent-empty.html │ ├── navcontent-empty.in.xml │ ├── navcontent-empty.template.xml │ ├── navcontent.html │ ├── navcontent.in.xml │ ├── navcontent.template.xml │ ├── navstyle-content-keep.html │ ├── navstyle-content-keep.template.xml │ ├── navstyle-content-list-keep.html │ ├── navstyle-content-list-keep.template.xml │ ├── navstyle-content-list-summarise.html │ ├── navstyle-content-list-summarise.template.xml │ ├── navstyle-content-summarise.html │ ├── navstyle-content-summarise.template.xml │ ├── navstyle-element-discard.html │ ├── navstyle-element-discard.template.xml │ ├── navstyle-element-keep-strip.html │ ├── navstyle-element-keep-strip.template.xml │ ├── navstyle-element-keep.html │ ├── navstyle-element-keep.template.xml │ ├── navstyle-element-repeat-strip.html │ ├── navstyle-element-repeat-strip.template.xml │ ├── navstyle-element-repeat-strip2.html │ ├── navstyle-element-repeat-strip2.template.xml │ ├── navstyle-none.html │ ├── navstyle-none.template.xml │ ├── navxml.html │ ├── navxml.in.xml │ ├── navxml.template.xml │ ├── simple.html │ ├── simple.in.xml │ └── simple.template.xml ├── json │ ├── article1.xml │ ├── article2.xml │ └── expect.json └── standalone │ ├── article-extra-attrs.html │ ├── article-extra-attrs.in.xml │ ├── article-extra-attrs.template.xml │ ├── article-from-attr.html │ ├── article-from-attr.in.xml │ ├── entities.html │ ├── entities.in.xml │ ├── escaped.html │ ├── escaped.in.xml │ ├── explicit-meta.html │ ├── explicit-meta.in.xml │ ├── extra-article.html │ ├── extra-article.in.xml │ ├── extra-templ-article.html │ ├── extra-templ-article.in.xml │ ├── implicit-meta.html │ ├── implicit-meta.in.xml │ ├── no-override-explicit-meta.html │ ├── no-override-explicit-meta.in.xml │ ├── no-override-implicit-meta.html │ ├── no-override-implicit-meta.in.xml │ ├── no-override-meta.html │ ├── override-explicit-meta.html │ ├── override-explicit-meta.in.xml │ ├── override-implicit-meta.html │ ├── override-implicit-meta.in.xml │ ├── set-get-escaped.html │ ├── set-get-escaped.in.xml │ ├── set-get-in-templ.html │ ├── set-get-in-templ.in.xml │ ├── set-get-in-templ.template.xml │ ├── set-get.html │ ├── set-get.in.xml │ ├── simple.html │ ├── simple.in.xml │ ├── simple.template.xml │ ├── tags-in-templ.html │ ├── tags-in-templ.in.xml │ ├── tags-in-templ.template.xml │ ├── tags.html │ └── tags.in.xml ├── sblg.h ├── sblg.in.1 ├── schema.json ├── template1.jpg ├── template2.jpg ├── template3.jpg ├── template4.jpg ├── template5.jpg ├── template6.jpg ├── tests.c ├── util.c └── versions.xml /.github/workflows/makefile.yml: -------------------------------------------------------------------------------- 1 | name: Regression Tests 2 | on: [push] 3 | jobs: 4 | linux: 5 | runs-on: ubuntu-latest 6 | steps: 7 | - uses: actions/checkout@master 8 | - name: Install dependencies 9 | run: sudo apt-get install -y bmake valgrind 10 | - name: Configure 11 | run: | 12 | cat /etc/os-release 13 | ./configure 14 | echo 'CFLAGS += -fsanitize=undefined,address' > Makefile.local 15 | echo 'LDFLAGS += -fsanitize=undefined,address' >> Makefile.local 16 | bmake regress 17 | rm -f Makefile.local 18 | bmake clean 19 | bmake valgrind 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # files generated by configure 2 | Makefile.configure 3 | Makefile.local 4 | config.h 5 | config.log 6 | # object files 7 | *.[oa] 8 | *.so.* 9 | *.so 10 | # vi swap files 11 | *.swp 12 | # generated files 13 | sblg 14 | sblg.1 15 | version.h 16 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012--2016, Kristaps Dzonsons 2 | 3 | Permission to use, copy, modify, and/or distribute this software for any purpose 4 | with or without fee is hereby granted, provided that the above copyright notice 5 | and this permission notice appear in all copies. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 9 | FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS 11 | OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 12 | TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF 13 | THIS SOFTWARE. 14 | 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Synopsis 2 | 3 | **sblg** is a utility for creating static blogs. It merges articles 4 | into templates, generating static HTML files, Atom feeds, and JSON 5 | files. It's built for use with `make`-style build environments. 6 | 7 | For stable releases, documentation, and general information, please visit 8 | https://kristaps.bsd.lv/sblg. 9 | 10 | If you have any comments or patches, please feel free to post them here. 11 | Feature requests will be just be closed, sorry! 12 | 13 | ## License 14 | 15 | All sources use the ISC license. 16 | See the [LICENSE.md](LICENSE.md) file for details. 17 | -------------------------------------------------------------------------------- /archive.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | sblg: version archive 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |

16 | sblg 17 | — simple off-line blog utility 18 |

19 |
20 |
21 |
22 |
23 | : 24 | version ${sblg-titletext} 25 |
26 |
27 | ${sblg-aside} 28 |
29 |
30 |
31 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /article.css: -------------------------------------------------------------------------------- 1 | html, body { margin: 0; 2 | padding: 0; } 3 | body { color: #333; 4 | line-height: 1.3em; 5 | font-size: 14pt; 6 | font-family: "Alegreya sans", sans-serif; 7 | font-weight: 400; } 8 | a { text-decoration: none; } 9 | aside { display: none; } 10 | body > article { width: 66rem; 11 | max-width: 98%; 12 | margin-left: auto; 13 | margin-right: auto; } 14 | body > header { background-color: #336699; } 15 | body > footer { padding: 2em 0; 16 | text-align: center; 17 | font-size: 90%; 18 | color: #999; } 19 | body > footer a { color: #444; } 20 | body > footer a:hover { color: #000; } 21 | .intro { opacity: 0.75; } 22 | p.code, 23 | pre { overflow-x: hidden; 24 | background-color: #f8f8f8; 25 | border-radius: 4pt; 26 | padding: 0.5rem !important; 27 | overflow-x: auto; 28 | border: none !important; 29 | font-size: 75%; } 30 | pre { line-height: 1.4em; } 31 | code { font-size: 75%; } 32 | .prettyprint a > * { color: blue !important; } 33 | p.code > code.tab { padding-left: 4ex; } 34 | p.code > code.dtab { padding-left: 8ex; } 35 | p.code > code { display: block; 36 | font-size: 100%; } 37 | pre:not(.prettyprint) > code { font-size: 100%; } 38 | .name { font-weight: 500; } 39 | strong, b { font-weight: 500; } 40 | body > header h1 { color: #ccc; 41 | font-size: 200%; 42 | font-weight: inherit; 43 | padding: 1rem 0; 44 | width: 66rem; 45 | max-width: 98%; 46 | margin: 0 auto; } 47 | body > header h1 a { color: #fff; } 48 | article[data-sblg-article] { margin-top: 2rem; } 49 | article[data-sblg-article] header 50 | { text-align: center; } 51 | article[data-sblg-article] h1, 52 | article[data-sblg-article] header h2 53 | { font-weight: 500; 54 | font-size: 125%; } 55 | article[data-sblg-article] h1 { text-align: center; } 56 | article[data-sblg-article] header > div 57 | { display: none; } 58 | 59 | @media only screen and (max-width: 768px), only screen and (max-device-width: 768px) { 60 | body > header h1 { font-size: 150%; 61 | text-align: center; } 62 | div.version { text-align: center; } 63 | article[data-sblg-article] h1, 64 | article[data-sblg-article] header h2 65 | { font-size: 110%; } 66 | } 67 | -------------------------------------------------------------------------------- /article.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | sblg: ${sblg-title} 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |

16 | sblg 17 | — static blog utility 18 |

19 |
20 |
21 |
22 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /article1.xml: -------------------------------------------------------------------------------- 1 |
2 |
3 |

How do I write articles?

4 |
Posted by
Kristaps Dzonsons
on
5 |
6 | 7 |

8 | Articles are fragments or full XML documents 9 | (usually HTML5). 10 | The simplest article is structured as follows: 11 |

12 |
<article data-sblg-article="1">
13 |   <header>
14 |     <h1>Title</h1>
15 |     <address>Kristaps Dzonsons</address>
16 |     <time datetime="2013-01-01">1 January, 2013</time>
17 |   </header>
18 |   <aside>
19 |     The article's <b>summary</b>
20 |   </aside>
21 |     <code>Mu.</code>
22 | </article>
23 |

24 | An article is any element with the data-sblg-article="1" Boolean attribute, usually 25 | <article data-sblg-article="1">. The 26 | article publication time is parsed from the first <time datetime=""> first 27 | <header>. 28 | The title is parsed from the first <hn> tag (where n = 1–4), 29 | as is the author from the <address> tag. 30 | These are used to order articles on the main page and title the article page. 31 | Both of these are optional — the system will default to Untitled article, Unknown author, and the file's 32 | ctime, if no information is otherwise provided. 33 | Furthermore, the first <aside> is used for the Atom summary. 34 |

35 |

36 | Articles are linked into a front page template as follows (and omitting the surrounding HTML stuff): 37 |

38 |
<body>
39 |   <nav data-sblg-nav="1" data-sblg-navsz="1"></nav>
40 |   <article data-sblg-article="1"></article>
41 | </body>
42 |

43 | Here, the <article data-sblg-article="1"> is replaced by ordered article data, 44 | with a little permanent link thing following. 45 | The <nav data-sblg-nav="1"> is replaced by newest-first blog posting history. 46 | The rest is up to you. 47 | The sblg(1) manual contains all the details. 48 |

49 |
50 | -------------------------------------------------------------------------------- /article10.md: -------------------------------------------------------------------------------- 1 | # How do I use Markdown? 2 | 3 | You can also use 4 | [markdown](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet) 5 | for your articles by using 6 | [lowdown](https://github.com/kristapsdz/lowdown) 7 | (or really any translator). 8 | 9 | [Markdown](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet) 10 | support isn't internal to [sblg(1)](https://kristaps.bsd.lv/sblg). 11 | However, you can easily use it by translating the Markdown text into 12 | XHTML and wrapping it with the appropriate `
` bits. 14 | 15 | ``` 16 | .md.xml: 17 | ( echo "" ; \ 18 | echo "
" ; \ 19 | lowdown $< ; \ 20 | echo "
" ; ) >$@ 21 | 22 | ``` 23 | 24 | I use [lowdown](https://github.com/kristapsdz/lowdown) because I wrote 25 | it (modernised fork of [hoedown](https://github.com/hoedown/hoedown)) 26 | and because it has some additional support for 27 | [sblg(1)](https://kristaps.bsd.lv/sblg) like annotating the first 28 | paragraph with an `