Tinkerer is a blogging engine/static website generator powered by Sphinx.

Overview

Tinkerer

https://travis-ci.org/vladris/tinkerer.png https://coveralls.io/repos/vladris/tinkerer/badge.png

What is Tinkerer?

Tinkerer is a blogging engine/static website generator powered by Sphinx.

It allows blogging in reStructuredText format, comes with out-of-the-box support for post publishing dates, authors, categories, tags, post archive, RSS feed generation, comments powered by Disqus and more.

Tinkerer is also highly customizable through Sphinx extensions.

Why Tinkerer?

  • Because "hacker" is way overused nowadays.
  • Because static websites are cool.
  • Because you already write documentation in RST format and you love it.
  • Because you have Pygments for sharing highlighted code.
  • Because you can use your favorite Sphinx extensions right away.

How to Tinker?

Get Tinkerer:

pip install tinkerer

Skim through the Documentation.

Comments
  • Exception while building the blog

    Exception while building the blog

    [hargup  blog  (gh-pages) ]$tinker --build
    Making output directory...
    Running Sphinx v1.2
    loading pickled environment... not yet created
    building [html]: targets for 11 source files that are out of date
    updating environment: 11 added, 0 changed, 0 removed
    reading sources... [100%] master                                                
    looking for now-outdated files... none found
    pickling environment... done
    checking consistency... done
    preparing documents... done
    writing output... [100%] master                                                 
    writing additional files...
    Exception occurred:
      File "/usr/lib/python2.7/xml/dom/expatbuilder.py", line 223, in parseString
        parser.Parse(string, True)
    ExpatError: junk after document element: line 8, column 0
    The full traceback has been saved in /tmp/sphinx-err-NEFQgD.log, if you want to report the issue to the developers.
    Please also report this if it was a user error, so that a better error message can be provided next time.
    Either send bugs to the mailing list at <http://groups.google.com/group/sphinx-users/>,
    or report them in the tracker at <http://bitbucket.org/birkenfeld/sphinx/issues/>. Thanks!
    

    Here's the log file

    # Sphinx version: 1.2
    # Python version: 2.7.3
    # Docutils version: 0.11 release
    # Jinja2 version: 2.7.1
    # Loaded extensions:
    #   tinkerer.ext.disqus from /usr/local/lib/python2.7/dist-packages/tinkerer/ext/disqus.pyc
    #   tinkerer.ext.blog from /usr/local/lib/python2.7/dist-packages/tinkerer/ext/blog.pyc
    #   sphinx.ext.oldcmarkup from /usr/local/lib/python2.7/dist-packages/sphinx/ext/oldcmarkup.pyc
    Traceback (most recent call last):
      File "/usr/local/lib/python2.7/dist-packages/sphinx/cmdline.py", line 246, in main
        app.build(force_all, filenames)
      File "/usr/local/lib/python2.7/dist-packages/sphinx/application.py", line 212, in build
        self.builder.build_update()
      File "/usr/local/lib/python2.7/dist-packages/sphinx/builders/__init__.py", line 214, in build_update
        'out of date' % len(to_build))
      File "/usr/local/lib/python2.7/dist-packages/sphinx/builders/__init__.py", line 273, in build
        self.finish()
      File "/usr/local/lib/python2.7/dist-packages/sphinx/builders/html.py", line 453, in finish
        for pagename, context, template in pagelist:
      File "/usr/local/lib/python2.7/dist-packages/tinkerer/ext/blog.py", line 107, in html_collect_pages
        for name, context, template in collect_additional_pages(app):
      File "/usr/local/lib/python2.7/dist-packages/tinkerer/ext/blog.py", line 86, in collect_additional_pages
        for name, context, template in rss.generate_feed(app):
      File "/usr/local/lib/python2.7/dist-packages/tinkerer/ext/rss.py", line 56, in generate_feed
        replace_read_more_link=not app.config.rss_generate_full_posts)),
      File "/usr/local/lib/python2.7/dist-packages/tinkerer/ext/patch.py", line 106, in patch_links
        doc = xml.dom.minidom.parseString(in_str)
      File "/usr/lib/python2.7/xml/dom/minidom.py", line 1930, in parseString
        return expatbuilder.parseString(string)
      File "/usr/lib/python2.7/xml/dom/expatbuilder.py", line 940, in parseString
        return builder.parseString(string)
      File "/usr/lib/python2.7/xml/dom/expatbuilder.py", line 223, in parseString
        parser.Parse(string, True)
    ExpatError: junk after document element: line 8, column 0
    
    opened by hargup 17
  • Add the ability to serve the blog locally for review.

    Add the ability to serve the blog locally for review.

    I have added a quick and easy way to view the blog locally before posting it to the Web. Hopefully this will help with developing themes for Tinkerer, as well as, give us an opportunity to check out posts prior to uploading them. I have added unit tests to verify that the server is pulling posts as expected.

    Thank you for your work on Tinkerer. It is great software and I have quite enjoyed hacking on it.

    opened by gisraptor 10
  • Date formatting depends on current locale

    Date formatting depends on current locale

    In metadata.py dates are formatted with .strftime() on date objects. This method is locale-aware and formats dates according to the current environment locale, that is, the value of $LANG or $LC_*.

    Hence, formatting of dates in posts depends on the environment in which Tinkerer is run, and ignores the language setting in conf.py.

    To build an English language blog on a system with, say, a German locale, you currently need to set LANG to en_US.utf8 explicitly (or a similar English-language locale) to make the post dates appear in English. Otherwise they will be German, i.e. Januar 1, 2013 instead of January 1, 2013.

    I can submit a pull request to fix this issue, but it would introduce a dependency against the Babel i18n library. Is that acceptable?

    opened by swsnr 10
  • Use tinkerer for a site (not a blog)

    Use tinkerer for a site (not a blog)

    IMHO, will be nice if can use tinkerer for write a site and not a blog. Do it must be "easy" since:

    • a blog must have a post in master.rst and
    • a site must have none post in master.rst and a page named index.rst or home.rst.

    For the above part I can write a patch. But I can't figure it out how to stop tinkerer stop try to generate the blog home page, any help?

    enhancement 
    opened by rgaiacs 9
  • Timestamp with post time (hh:mm:ss)

    Timestamp with post time (hh:mm:ss)

    It would be really cool if we could have publication time in the post timestamp.

    This is useful if you write several posts a day. It's vital for blogs used to indicate some online service status.

    wontfix 
    opened by moigagoo 6
  • asset compression

    asset compression

    Hay there, i'm looking for sth. like http://django-pipeline.readthedocs.org/en/latest/compressors.html for tinkerer. Is there any option/plugin for asset compression? Actually i never worked with sphinx or tinkerer, but i can't believe there is no such extension.

    Thanks in advance, Lukas

    opened by sakulstra 5
  • PyQuery implementation of make_read_more_link() is not always working

    PyQuery implementation of make_read_more_link() is not always working

    If the <div id="more"> is enclosed by <div id="some-other-div"> then doc('p.readmorewrapper').next_all().remove() will not remove everything that should be removed. Sometimes it works, sometimes not, it depends where the .. more:: gets inserted.

    Example:

    make_read_more_link:

    def make_read_more_link(body, docpath, docname):
        """
        Create "read more" link if marker exists.
        """
        doc = pyquery.PyQuery(body)
        link_p = ('<p class="readmorewrapper"><a class="readmore" '
                  'href="%s.html#more">%s</a></p>' %
                  (docpath + docname, UIStr.READ_MORE))
        doc('div#more').replaceWith(link_p)
        doc('p.readmorewrapper').next_all().remove()
        return doc.html()
    
    

    body:

    <h1>Example</h1>
    <div class="figure align-center">
    </div>
    <p>....</p>
    <p>Why?</p>
    
    <div id="some-other-div">
    
    Text...
    
    <div id="more"> </div>
    
    </div>
    
    <p>more text</p>
    
    <p>...</p>
    
    </div>
    

    IPython session:

    In [19]: body='''
    <h1>Example</h1>
    <div class="figure align-center">
    </div>
    <p>....</p>
    <p>Why?</p>
    <div id="some-other-div">
    Text...
    <div id="more"> </div>
    </div>
    <p>more text</p>
    <p>...</p>
    </div>
    '''
    
    In [20]: doc = pyquery.PyQuery(body)
    
    In [21]: link_p = ('<p class="readmorewrapper"><a class="readmore" '
       ....:                 'href="%s.html#more">%s</a></p>' %
       ....:                 ("/index.html", "READ_MORE"))
    
    In [22]: doc('div#more').replaceWith(link_p)
    Out[22]: [<div#more>]
    
    In [23]: doc('p.readmorewrapper').next_all().remove()
    Out[23]: []
    
    In [24]: doc.html()
    Out[24]: u'<h1>Example</h1>\n
    <div class="figure align-center">\n
    </div>\n
    <p>....</p>\n
    <p>Why?</p>\n
    <div id="some-other-div">\n
    Text...\n
    <p class="readmorewrapper"><a class="readmore" href="/index.html.html#more">READ_MORE</a></p>\n
    </div>\n
    <p>more text</p>\n
    <p>...</p>\n\n'
    
    In [25]: 
    

    <p>more text</p>... should have been removed.

    I'm currently investigating solutions... But maybe @dhellmann has a good idea?

    opened by christianjann 5
  • Allow `html_use_index`

    Allow `html_use_index`

    I'd like to enable the html_use_index option found here:

    https://github.com/vladris/tinkerer/blob/master/tinkerer/__templates/conf.py#L93

    Out of the box, tinkerer errors as it can't find the genindex.html template, but I copied the one over from sphinx and dropped it in the themes/boilerplate directory and it worked fine.

    Would the project be opposed to me submitting a PR to allow this option?

    opened by gdw2 5
  • Rewrite patch with pyquery for robustness

    Rewrite patch with pyquery for robustness

    Not all HTML can be parsed with a strict XML parser. Some Sphinx extensions insert HTML from sources outside of the local author's control (sphinxcontrib-embedly, for example). In order to support RSS feeds with valid links and the embedded content from these extensions, use a more forgiving HTML parser when patching the links.

    Change-Id: I045e338289b63832315210b31a7188d5c6ab6570

    opened by dhellmann 5
  • Permit choice of dash to separate words in page and post names.

    Permit choice of dash to separate words in page and post names.

    A word_sep keyword argument is added to several functions and is ultimately used in utils.name_from_title(). I also ensure that only one instance of the word sep char appears between words and that there are no leading or trailing non-word chars in the name. I'd like to propose the same for other page/post/draft creation options.

    I just found Tinkerer yesterday and it seems to be exactly what I've been looking for in a blogging tool!

    opened by sgillies 5
  • Enable html_link_suffix

    Enable html_link_suffix

    I want to control the extension for internal links. For example, if you hide the extension using the MultiViews feature of Apache. This is a patch for that.

    Fixes summary

    • Change to app.config.html_link_suffix from hard code '.html'(Sphinx has html_link_suffix)
    • Add html_link_suffix to MetaData class
    • Append html_link_suffix to metadata.link
    opened by yotchang4s 5
  • docs: Fix a few typos

    docs: Fix a few typos

    There are small typos in:

    • blog/2012/07/05/tinkerer_0_4_beta_released.rst
    • blog/2013/06/05/tinkerer_1_2_released.rst
    • blog/doc/extensions.rst
    • blog/pages/extensions.rst
    • tinkerer/ext/filing.py
    • tinkerer/ext/metadata.py
    • tinkertest/test_categories.py
    • tinkertest/test_cmdline.py
    • tinkertest/test_master.py
    • tinkertest/test_patch.py

    Fixes:

    • Should read repository rather than respository.
    • Should read exists rather than exsits.
    • Should read documentation rather than documententation.
    • Should read development rather than developement.
    • Should read containing rather than containig.
    • Should read compatibility rather than compatiblity.
    • Should read category rather than cateogry.
    • Should read categories rather than categoires.
    • Should read categories rather than caregories.
    • Should read appended rather than appendend.
    • Should read aggregate rather than aggreated.

    Semi-automated pull request generated by https://github.com/timgates42/meticulous/blob/master/docs/NOTE.md

    opened by timgates42 0
  • REF: py38, sphinx>=1.7.0, try/except add_config_value(

    REF: py38, sphinx>=1.7.0, try/except add_config_value("author")

    Sphinx 3.2.1 already defines a config value named author, so this patch just passes when an ExtensionError is raised when trying to add_config_value("author").

    The tests pass with tox (upgraded to py38) and local output appears to be unchanged from building before this patch.

    closes #112

    closes #117

    There's a new nonfatal error which may be resolved by a fix for #114 (~Allow passthrough configuration from conf.py)

    tinker --build
    Running Sphinx v3.2.1
    WARNING: The config value `html_add_permalinks' has type `NoneType', defaults to `str'.
    

    Is that a regression, or can this be merged?

    opened by westurner 0
  • Bypassed: Use sphinx 1.7.1 in combination with tinkerer and sphinx 3.1.2 as standalone

    Bypassed: Use sphinx 1.7.1 in combination with tinkerer and sphinx 3.1.2 as standalone

    This issue is bypassed, not solved. I've posted it anyway, so that others might use the bypass solution described here or can help to get a better solution.

    Issue of using sphinx stand alone and in combination with tinkerer

    Tinkerer 1.7.2 has Sphinx 1.7.1 as requirement. The latest Sphinx is 3.1.2 (July 2020) and I'm also Sphinx as standalone (without tinkerer) and would like to use the latest version. When I first install sphinx:

    pip install sphinx

    I get version 3.1.2, but when I also install tinkerer:

    pip install tinkerer

    The output mentions that sphinx is downgraded to version 1.7.1 due to tinkerer requirements.

    Considered but not chosen solutions

    A python virtual environment cannot handle this as it can only handle different python versions, e.g. 3.7 and 3.8, but not different module versions. I've also considered pipenv and poetry, but these require configuration files and seems to be more oriented towards developers and I wanted something more simple. A virtual machine like virtualbox seems to be too much overload.

    Chosen solution

    The chosen solution uses pipx and is described here.

    First remove tinkerer and sphinx from your installation:

    pip uninstall sphinx
    pip uninstall tinkerer
    
    

    I'm using (K)ubuntu with the aptitude package manager and installed pipx via:

    sudo aptitude -y install pipx
    pipx ensurepath
    

    Without aptitude, you might want to use apt or apt-get. Pipx can be installed in many other ways, see: pipx .

    When I tried tinkerer this way to generate my website, I got error messages, and I found out Tinkerer calls Sphinx via a subprocess (instead of 'within' python), Hence, it breaks out of the pipx virtual python environment... This can be prevented by editing the file (using the nano editor):

    nano ~/.local/pipx/venvs/tinkerer/lib/python3.8/site-packages/tinkerer/cmdline.py

    and change line 49 from flags = ["sphinx-build"] to:

    flags = ["~/.local/pipx/venvs/tinkerer/bin/sphinx-build"]

    When you want to use additional modules, you also have to add them in pipx, as for example to add matplotlib:

    pipx inject tinkerer requests matplotlib

    I also made some changes to the conf.py file, perhaps not needed... but anyway:

    • tinkerer imports at the beginning are commented out... they are already loaded elsewhere, hence not needed
    • all references to tinkerer _themes and _static are removed... as I use self defined, locally stored _themes and _static
    • some variables are hard-coded instead of referring to tinkerer settings as in:
    source_suffix = ".rst"
    master_doc = "master"
    

    Now tinkerer generates my website fluently, using sphinx 1.7.1

    I can now also install sphinx latest version:

    pip install --upgrade sphinx

    which gives me version 3.1.2. And this runs well

    opened by Dutchtallman 0
  • Allow configuration of builddir (paths.blog, paths.html etc.) in conf.py

    Allow configuration of builddir (paths.blog, paths.html etc.) in conf.py

    AFAIK there's no way to force Tinkerer where to build it's output. This is essential configuration that should be modifiable in conf.py with variables e.g. thinker_blog_dir, thinker_html_dir etc.

    opened by mattwarrick 1
  • Updates sphinx dependency

    Updates sphinx dependency

    Hi,

    I fixes to support Sphinx 2.3.0, and Python 3.7, 3.8. If you like, could you please merge the pull request?

    The main modifications are as follows.

    1. tox on python 3.7, python3.8.
    • Appends setenv = LANG = C for Non-English LANG.
    • Drops Python 3.6 supports. (Python 3.6 does not work on Debian GNU/Linux bullseye/Sid.)
    1. Fixes config.author bug for Sphinx >= 1.8.0.
    2. Fixes sphinx.main() of unittest for Sphinx >= 2.0.0.
    3. Fixes setup argument test_requries.
    4. Supports Sphinx version >= 2.3.0.

    I develops and tests using Pipenv.

    $ pipenv --python 3.7
    $ pipenv install tox
    $ pipenv run tox
    

    But not fixes RemovedInSphinx30Warning.

    /path/to/tinkerer/tinkerer/themes/boilerplate/search.html:20: 
    RemovedInSphinx30Warning: To modify script_files in the theme is deprecated.
    Please insert a <script> tag directly in your theme instead.
    

    Best regards,

    opened by mkouhei 1
  • Build error with Sphinx-1.8.1

    Build error with Sphinx-1.8.1

    This currently fails with

    $ tinker --build
    Running Sphinx v1.8.1
    
    Extension error:
    Config value 'author' already present
    

    The problem goes away by remove the line

    app.add_config_value("author", "Winston Smith", True)
    

    in https://github.com/vladris/tinkerer/blob/master/tinkerer/ext/blog.py#L126

    The problem of course is that pip install tinkerer is currently broken because it does not pin the version of Sphinx to its tested version.

    opened by scudette 2
A Python Static Website Generator

Version 0.8.9 Overview Hyde starter kit by merlinrebrovic is a really nice way to get started with hyde. Hyde layout for bootstrap by auzigog is also

Hyde - Static Website Generator 1.6k Jan 1, 2023
a static website generator to make beautiful customizable pictures galleries that tell a story

Prosopopee Prosopopee. Static site generator for your story. Make beautiful customizable pictures galleries that tell a story using a static website g

Bram 259 Dec 19, 2022
A static website generator for people who enjoy the simpler things in life.

A static website generator for people who enjoy the simpler things in life.

Darren Mulholland 93 Dec 22, 2022
Simple, lightweight, and magic-free static site/blog generator for Python coders

makesite.py Take full control of your static website/blog generation by writing your own simple, lightweight, and magic-free static site generator in

Sunaina Pai 1.7k Jan 1, 2023
A simple static site generator with deployment to S3/Cloudfront.

Stasis A simple static site generator with deployment to S3/Cloudfront. Features Stasis is a static website generator written in Python, using Pandoc

Scott Czepiel 56 Sep 29, 2022
dirmaker is a simple, opinionated static site generator for quickly publishing directory websites.

dirmaker is a simple, opinionated static site generator for publishing directory websites (eg: Indic.page, env.wiki It takes entries from a YAML file and generates a categorised, paginated directory website.

Kailash Nadh 40 Nov 20, 2022
Static site generator for designers. Uses Python and Django templates.

News Cactus 3 is out! We're happy to announce Cactus 3. It brings a set of great new features like asset fingerprinting, an asset pipeline, pretty url

null 3.4k Jan 1, 2023
AutoLoader is a plugin for Pelican, a static site generator written in Python.

AutoLoader AutoLoader is a plugin for Pelican, a static site generator written in Python. AutoLoader is designed to autoload the other Pelican plugins

null 2 Nov 7, 2022
Kaktos is a python static site generator

Python static site generator κάκτος Kaktos is a python static site generator. The idea is create a simple static site generator for people that don't

Paulo Coutinho 4 Sep 21, 2022
barely is a lightweight, but highly extensible static site generator written in pure python.

barely is a lightweight, but highly extensible static site generator. Explore the docs » Quickstart · See available Plugins · Report Bug · Request Fea

null 40 Dec 1, 2022
A python-based static site generator for setting up a CV/Resume site

ezcv A python-based static site generator for setting up a CV/Resume site Table of Contents What does ezcv do? Features & Roadmap Why should I use ezc

Kieran Wood 5 Oct 25, 2022
A declarative website generator designed for high-quality websites, with a focus on easy maintenance and localization.

Grow Grow is a declarative tool for rapidly building, launching, and maintaining high-quality static HTML. Easy installation Jinja template engine Con

Grow 385 Dec 3, 2022
The lektor static file content management system

Lektor Lektor is a static website generator. It builds out an entire project from static files into many individual HTML pages and has a built-in admi

Lektor CMS 3.6k Dec 29, 2022
Makes dynamic linked shit "static". Amazing

static.py What does it do? You give it a dynamically linked binary and it will make a directory that has all the dependencies (recursively). It also f

Stephen Tong 24 Dec 16, 2022
Simple Static Site Inductor Made in Python

sssimp ?? Simple Static Site Inductor Made in Python How to use Create a folder called input, inside create a folder called content and an empty file

Tina 11 Oct 9, 2022
Hobby Project. A Python Library to create and generate static web pages using just python.

PyWeb ??️ ?? Current Release: 0.1 A Hobby Project ?? PyWeb is a small Library to generate customized static web pages using python. Aimed for new deve

Abhinav Sinha 2 Nov 18, 2021
Sphinx-performance - CLI tool to measure the build time of different, free configurable Sphinx-Projects

CLI tool to measure the build time of different, free configurable Sphinx-Projec

useblocks 11 Nov 25, 2022
Static site generator that supports Markdown and reST syntax. Powered by Python.

Pelican Pelican is a static site generator, written in Python. Write content in reStructuredText or Markdown using your editor of choice Includes a si

Pelican dev team 11.3k Jan 4, 2023
Static site generator that supports Markdown and reST syntax. Powered by Python.

Pelican Pelican is a static site generator, written in Python. Write content in reStructuredText or Markdown using your editor of choice Includes a si

Pelican dev team 11.3k Jan 5, 2023
This is a simple website crawler which asks for a website link from the user to crawl and find specific data from the given website address.

This is a simple website crawler which asks for a website link from the user to crawl and find specific data from the given website address.

Faisal Ahmed 1 Jan 10, 2022