{"id":19136834,"url":"https://github.com/mdub/pith","last_synced_at":"2025-04-16T01:28:49.427Z","repository":{"id":56888146,"uuid":"703163","full_name":"mdub/pith","owner":"mdub","description":"a static website generator","archived":false,"fork":false,"pushed_at":"2020-04-21T00:57:26.000Z","size":312,"stargazers_count":38,"open_issues_count":0,"forks_count":6,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-29T03:32:05.172Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mdub.png","metadata":{"files":{"readme":"README.markdown","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2010-06-04T12:16:04.000Z","updated_at":"2020-04-21T00:57:29.000Z","dependencies_parsed_at":"2022-08-21T00:20:59.250Z","dependency_job_id":null,"html_url":"https://github.com/mdub/pith","commit_stats":null,"previous_names":[],"tags_count":21,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdub%2Fpith","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdub%2Fpith/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdub%2Fpith/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdub%2Fpith/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mdub","download_url":"https://codeload.github.com/mdub/pith/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248717247,"owners_count":21150389,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-09T06:35:39.435Z","updated_at":"2025-04-16T01:28:49.404Z","avatar_url":"https://github.com/mdub.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"Pith [![Build Status](https://secure.travis-ci.org/mdub/pith.png?branch=master)](http://travis-ci.org/mdub/pith)\n====\n\nPith is a static website generator, written in Ruby.\n\nUsing Pith, you can:\n\n* Lay-out your page designs in [Haml][haml], ERb, or Liquid.\n* Style things up using [Sass][sass].\n* Succintly add content using Markdown or Textile.\n* Encapsulate common markup in \"layout\" and \"partial\" templates.\n* Easily link pages (and resources) using relative links.\n* Test changes quickly using the built-in web-server.\n\nInstall it\n----------\n\nPith is packaged as a Ruby gem.  Assuming you have Ruby, install it thusly:\n\n    gem install pith\n\nQuickstart\n----------\n\nCreate an input directory for your site (wherever you want), and pop some files into it:\n\n    SITE/\n      _pith/\n      images/\n        logo.png\n      index.html.haml\n\nThe only requirement is the existance of a subdirectory called \"`_pith`\".  Pith checks that it's present, to prevent you accidently treating your entire home directory as website input.\n\nNext, use the `pith build` command to convert your inputs into a functioning website.\n\n    $ pith -i SITE build\n    Generating to \"SITE/_out\"\n    --(copy)--\u003e   images/logo.png\n    --(haml)--\u003e   index.html\n\nBy default, output is generated into an subdirectory called \"`_out`\", inside the input directory ... but the default can be easily overridden, e.g.\n\n    $ pith -i SITE -o OUTPUT build\n\nTemplates\n---------\n\nFiles in the input directory are considered to be \"templates\" if the file name ends with a template format extension recognised as such by [Tilt][tilt], e.g. \"`.haml`\", or \"`.textile`\".  These will be evaluated dynamically.  Pith strips the format extension off the file name when generating output.\n\nTilt supports a wide variety of formats, including:\n\n- [Markdown](http://daringfireball.net/projects/markdown/) (`markdown`, `md`)\n- [Textile](http://redcloth.org/hobix.com/textile/) (`textile`)\n- [Haml][haml] (`haml`)\n- [Erb](http://ruby-doc.org/stdlib/libdoc/erb/rdoc/classes/ERB.html) (`erb`)\n- [Sass][sass] (`sass`)\n- [CoffeeScript](http://jashkenas.github.com/coffee-script/) (`coffee`)\n\nAt one end of the spectrum are the \"template engines\", like ERB/Erubis and Liquid, which allow insertion of dynamic content into a template.  These aren't really HTML-specific; they can be used to generate any output format ... really, they're just string interpolation on steroids.\n\nAt the other end of the spectrum are \"markup formats\" like Markdown, Textile, Creole, which are targeted specifically at HTML output ... but don't support insertion of dynamic content.\n\nIn the middle are hybrids like Haml, and Markaby, which are both HTML-focused, but support dynamic content.\n\nPipelining\n----------\n\nIf you want both dynamic content, and simplified markup, in the same template, one option is to use Haml.\n\nThe alternative to Haml, if you want both dynamic content, and less angle-bracket, is to combine a template format with a markup format.  For example, you can create a \"page.md.liquid\" template, which would undergo first Liquid template expansion (for dynamic content), and then Markdown processing (for generation of HTML).\n\nResources\n---------\n\nAny non-template input files (we call them \"resources\") are just copied verbatim into the output directory.\n\nIgnored files\n-------------\n\nFiles or directories beginning with an underscore are ignored; that is, we don't generate corresponding output files.  They can still be used as \"layout\" or \"partial\" templates though; see below.\n\nPage metadata\n-------------\n\nA YAML header can be provided at the top of any template, defining page metadata.  The header is introduced by a first line containing three dashes, and terminated by a line containing three dots.\n\n    ---\n    title: \"Fish\"\n    subtitle: \"All about fish\"\n    ...\n\nMetadata provided in the header can be referenced by template content, via the \"`page.meta`\" Hash:\n\n    %html\n      %head\n        %title= page.meta[\"title\"]\n      %body\n        %h1= page.meta[\"title\"]\n        %h2= page.meta[\"subtitle\"]\n\nThis is especially useful in \"layout\" templates (see below).\n\nSince the page title is such a common thing to want to specify in the header, it's also available as \"`page.title`\", as a shortcut (if no explicit title was provided, Pith will guess one from the input file name).\n\nPartials and Layouts\n--------------------\n\nTemplates can include other templates, e.g.\n\n     = include \"_header.haml\"\n\nWhen including, you can pass local variables, e.g.\n\n    = include \"_list.haml\", :items =\u003e [1,2,3]\n\nwhich can be accessed in the included template:\n\n    %ul\n      - items.each do |i|\n        %li= i\n\nIn Haml templates, you can also pass a block, e.g.\n\n    = include \"_mylayout.haml\" do\n      %p Some content\n\nand access it in the template using \"`yield`\":\n\n    !!!\n    %html\n      %body\n        .header\n          ... blah blah ...\n        .main\n          = yield\n\nThis way, any template can be used as a \"layout\".\n\nLayouts can also be applied by using a \"`layout`\" entry in the page header, e.g.\n\n    ---\n    layout: \"/_mylayout.haml\"\n    ...\n\n    Some content\n\nRelative links\n--------------\n\nIt's sensible to use relative URIs when linking to other pages (and resources) in your static site, making the site easier to relocate.  But generating relative-links from partials and layouts is tricky.  Pith makes it easy with the \"`href`\" function:\n\n    %a{:href =\u003e href(\"other.html\")} Other page\n\n    %img{:src =\u003e href(\"/images/logo.png\")}\n\nAny path beginning with a slash (\"/\") is resolved relative to the root of the site; anything else is resolved relative to the current input-file (even if that happens to be a layout or partial).  Either way, \"`href`\" always returns a relative link.\n\nThere's also a \"`link`\" function, for even easier hyper-linking:\n\n    link(\"other.html\", \"Other page\")\n\nConfiguring Pith\n----------------\n\nThe behaviour of Pith can be customised somewhat, by dropping a \"`config.rb`\" file into the \"`_pith`\" directory.\n\nThere are a couple of flags that can be set to modify generation of links using \"`href`\" and \"`link`\":\n\n    project.assume_content_negotiation = true\n    project.assume_directory_index = true\n\nBoth flags default to false.  When `assume_content_negotiation` is enabled, Pith omits the \".html\" suffix from links.  When `assume_directory_index` is enabled, Pith abbreviates links to \"index.html\" files.  Both of these assumptions work nicely when the generated files are served using a web-server such as Apache httpd, but aren't appropriate if you wish to navigate them as static files on the filesystem.\n\nIt's also possible to mix behaviour into Pith, using the config file, e.g.\n\n    project.helpers do\n\n      def handy_method\n        # ...\n      end\n\n    end\n\nAny methods defined in a `project.helpers` block are available for use in templates.\n\nFor a more extensive example of a config file, look [over here](https://github.com/mdub/dogbiscuit.org/blob/master/src/_pith/config.rb).\n\nIncremental rebuild\n-------------------\n\nFor quick prototyping, use the \"`watch`\" command, rather than \"`build`\".  After building your site, Pith will stay running, and regenerate output files (as necessary) as you edit the inputs.  We keep track of which input files are involved in the production of each output, so only the affected outputs are re-generated.\n\n    $ pith -i SITE watch\n    Generating to \"SITE/_out\"\n    --\u003e images/logo.png\n    --\u003e index.html\n    # ... edit \"index.html.haml\" ...\n    --\u003e index.html\n\nBuilt-in web-server\n-------------------\n\nFor even quicker prototyping, Pith includes a simple HTTP server.  Start it by using the \"`serve`\" command, rather than \"`build`\"\n\n    $ pith -i SITE serve\n    Generating to \"SITE/_out\"\n    --\u003e images/logo.png\n    --\u003e index.html\n    Taking the Pith at \"http://localhost:4321\"\n    \u003e\u003e Thin web server (v1.2.7 codename No Hup)\n    \u003e\u003e Maximum connections set to 1024\n    \u003e\u003e Listening on 0.0.0.0:4321, CTRL+C to stop\n\nPith will incrementally re-build the site as you browse -- that is, if you alter any input files, Pith will regenerate the affected outputs.\n\nAdd the \"`--live`\" option to \"`serve`\" to enable [Live.js][livejs], for live-reloading of HTML, CSS and Javascript.\n\nPlugins\n-------\n\nPith includes a couple of optional \"plugins\".  Actually, \"plugin\" is a bit strong: they're just plain old Ruby modules that extend Pith's functionality.\n\n### Publication plugin\n\nThe 'publication' plugin makes it easier to build a weblog using Pith.\n\nEnable it by requiring it in your \"`config.rb`\", like so:\n\n    require \"pith/plugins/publication\"\n\nNow you can specify a \"published\" date/time in the metadata of any pages you consider to be \"articles\", e.g.\n\n    ---\n    title: Introducing ShamRack\n    published: 3-July-2009, 15:50\n    ...\n\nThis exposes \"`page.published_at`\" for use in your templates.\n\nIn addition, \"`project.published_inputs`\" lists all the pages that have such a timestamp, in order of publication, making it easy to build index pages and XML feeds.  Here's a example, used to build the article index for [dogbiscuit.org](http://dogbiscuit.org/mdub/weblog):\n\n    %ul.articles\n      - project.published_inputs.reverse.each do |entry|\n        %li\n          %p\n            = link(entry)\n            %span.teaser\n              %span.published_at\n                on\n                = entry.published_at.strftime(\"%e %b, %Y\")\n\n### Compass plugin\n\nThe Compass plugin gives you the full power of [Compass][compass] in your Sass stylesheets.  Enable it by requiring it in your \"`config.rb`\":\n\n    require \"pith/plugins/compass\"\n\nNote that if you're using Bundler, you'll also need to include the Compass gem in your `Gemfile`.\n\n    gem \"compass\"\n\n[tilt]: http://github.com/rtomayko/tilt/\n[haml]: http://haml-lang.com\n[sass]: http://sass-lang.com\n[compass]: http://compass-style.org\n[livejs]: http://livejs.com\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmdub%2Fpith","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmdub%2Fpith","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmdub%2Fpith/lists"}