{"id":16926986,"url":"https://github.com/runxel/morris","last_synced_at":"2025-07-22T15:34:38.944Z","repository":{"id":91517921,"uuid":"243291308","full_name":"runxel/Morris","owner":"runxel","description":"Framework for use with pandoc.","archived":false,"fork":false,"pushed_at":"2020-10-25T18:24:03.000Z","size":737,"stargazers_count":7,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-07-21T21:37:12.872Z","etag":null,"topics":["css","css-framework","markdown","markdown-to-html","markdown-to-pdf","pandoc","pandoc-css","pandoc-template","pandoc-templates","weasyprint"],"latest_commit_sha":null,"homepage":null,"language":"CSS","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/runxel.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":"runxel","patreon":null,"open_collective":null,"ko_fi":"runxel","tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":null}},"created_at":"2020-02-26T15:05:10.000Z","updated_at":"2025-03-04T06:13:55.000Z","dependencies_parsed_at":null,"dependency_job_id":"944d089a-f55e-4575-acbc-bf0157a96e82","html_url":"https://github.com/runxel/Morris","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/runxel/Morris","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/runxel%2FMorris","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/runxel%2FMorris/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/runxel%2FMorris/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/runxel%2FMorris/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/runxel","download_url":"https://codeload.github.com/runxel/Morris/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/runxel%2FMorris/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266521183,"owners_count":23942398,"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","status":"online","status_checked_at":"2025-07-22T02:00:09.085Z","response_time":66,"last_error":null,"robots_txt_status":null,"robots_txt_updated_at":null,"robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["css","css-framework","markdown","markdown-to-html","markdown-to-pdf","pandoc","pandoc-css","pandoc-template","pandoc-templates","weasyprint"],"created_at":"2024-10-13T20:32:26.681Z","updated_at":"2025-07-22T15:34:38.930Z","avatar_url":"https://github.com/runxel.png","language":"CSS","funding_links":["https://github.com/sponsors/runxel","https://ko-fi.com/runxel"],"categories":[],"sub_categories":[],"readme":"# Morris\n\n\u003c!-- TODO:\n - pictures for gen. PDF like 'Gutenberg'\n --\u003e\n\n\u003cimg align=\"right\" src=\"img/morris-logo.png\" width=\"150\"\u003e\n\n\u003e Make creating documents a pleasure.\n\n[![license](https://img.shields.io/github/license/runxel/Morris?style=flat-square)]()\n\nPandoc is an incredibly powerful tool – which comes at the cost of being sometimes seemingly too complex.\nThis project aims to lower the hurdles and make document creating an easy thing. Morris provides you with everything you need to quickly generate beatiful documents from your Markdown.\n\nLet's start! It's as easy as:\n\n## Usage\n\n```shell\nmake\n```\n\n## Features\n\nMorris comes with a `makefile` you can modify to your liking.\n\n- `make` will output a PDF for every `.md` file in the directory.\n- `make both` will give you PDF \u0026 HTML.\n- `make all` will output PDF, HTML, Word \u003csamp\u003e.docx\u003c/samp\u003e, OpenOffice \u003csamp\u003e.odt\u003c/samp\u003e, and InDesign \u003csamp\u003e.icml\u003c/samp\u003e.\nYou can also be specific in what you generate by using the format as a \u003csamp\u003emake\u003c/samp\u003e option, e.g. `make icml`.\n- `make clean` will delete all generated content in the `OUTPUT_PATH` folder.\n\n_Don't panic when seeing complaints about unknown CSS rules in your CLI: some boilerplate in the `morris.css` is for generating nice HTML – it is expected to make no sense in printing and vice versa._\n\n- The HTML output has a simple lightbox enabled when using the `.lightbox` class on your images. \n\n\n### Your Markdown\nBe sure to include some [metadata](https://pandoc.org/MANUAL.html#variables) in your Markdown files:\nUse a YAML block right at the file's beginning. Otherwise you can write in the same way you would always do.\n\n\n### On PDFs\nThere are different ways to get a PDF from a Markdown document in Pandoc. The default action requires a LaTeX version to be installed. I'm not a big fan of this (using the Markdown/Pandoc combination was to avoid LaTeX in the first place).\nPandoc however supports a wide range of [other engines](https://pandoc.org/MANUAL.html#option--pdf-engine), mostly with HTML as an intermediate format. Something which appeals to me much more coming from the web.\n\nInteresting are `wkhtmltopdf` and `weasyprint`. [Prince](https://www.princexml.com/) might be good, but it's proprietary and unaffordable if you aren't a multi-billion dollar company.  \n[**Wkhtmltopdf**](https://wkhtmltopdf.org/) is the next option here:  \nHowever, the default will output an unreadable, smashed pile of text. You need a lot of styling to get something halfway decent.\nThis leads to more problems down the road. Wkthml uses a neolithic version of WebKit which makes it hardly usable (printing is no concern to the WebKit devs). Also none of the newer CSS stuff we got to like in the near past is supported. This already starts with trivial things like CSS variables (aka _custom properties_).\nSoon enough you will be ridden with lots of meaningless errors and _man_, inserting a pagination is an endeavour on loosing your mind. And don't spend your time thinking about [hyphenation](https://github.com/wkhtmltopdf/wkhtmltopdf/issues/1730).\n\nYounger and maybe less atrocious is [**Weasyprint**](https://weasyprint.org/).  \n_Caveat for Windows users_: Weasyprint has a horrible and ridiculous way of [installation](https://weasyprint.readthedocs.io/en/stable/install.html#windows) – you have to install the GTK3 runtime…\n\u003csub\u003eHint for Miniconda/Anaconda users: Since weasyprint is Python-based you might have to activate the right environment first (à la `activate \u003cpy3\u003e`).\u003c/sub\u003e\n\nOnce you got through the painful installation weasyprint appears to be quite nice and much more usable than wkhtml.  \n***If*** you intend to use the `makefile` you don't need to care anyway, because you need `GNU make` for that – meaning you should use [Cygwin](https://www.cygwin.com/) or the [Windows Subsystem for Linux WSL](https://docs.microsoft.com/en-us/windows/wsl/install-win10) (Win10 only).  \n\u003csub\u003eI _have_ tried to use NMAKE in Windows [by using Qt's _Jom_, a drop-in replacement], but it is too limited. Don't waste time on that and use WSL instead.\u003c/sub\u003e\n\nIn case you _are_ a Windows user and want to proceed with WSL to use the makefile there is one thing to take care of: You are most likey referecing fonts that aren't available in your Linux subsystem but in Windows natively. How to do that is written down [here](https://x410.dev/cookbook/wsl/sharing-windows-fonts-with-wsl/).\n\nWeasyprint supports CSS' `@page` rules (designed for [paged media](https://www.quackit.com/css/at-rules/css_page_at-rule.cfm) so we can easily pass a custom CSS via the usual Pandoc CLI param:\n\n```shell\npandoc input.md -o output.pdf --pdf-engine=weasyprint -c morris.css\n```\n\u003cbr\u003e\n\nHowever, in the end, the [sad state of automated layouting solutions](https://mb21.github.io/blog/2016/08/13/The-sad-state-of-automated-layouting-solutions) didn't got better in the last 10 years. Proper engine support is still lacking many features. So regarding your own CSS: better keep it simple. (Think of styling an email – both has some 90's vibe to it.)\n\n\n## Utilities\nYou might want to enjoy the possibility to number figures, equations, tables and cross-reference them. This can be done with the [pandoc-crossref filter](https://github.com/lierdakil/pandoc-crossref).  \nWith [pandoc-plot](https://github.com/LaurentRDC/pandoc-plot) will turn your code blocks (Matplotlib, MATLAB, Mathematica, graphviz, and more) into embedded figures.\n\n\n## Caution\n**Be sure** you have a recent pandoc version. The versions in the package managers are usually _heavily_ outdated. Also follow the complete [weasyprint installation](https://weasyprint.readthedocs.io/en/stable/install.html) process.\n\n\n## Automation\nIf you want to have an auto-conversion taking place everytime you push to your repo: That's possible with [GitHub Actions](https://github.com/pandoc/pandoc-action-example)!\n\n\n## Trivia\nThis project was named in honor of [William Morris](https://en.wikipedia.org/wiki/William_Morris).\n\n---\n\n## Print CSS explained\n\n\u003cdetails\u003e\n\nThe biggest difference in understandinng CSS is tied to the viewport and the page model. Whereas on the web we finally have let go of fixed viewport sizes meaning everything is fluid the opposite is true for print: We suddenly have no longer a continuous media, but discrete pages with finite space to fill.\n\nAlso there are new concepts which have no analogy on the web.\n\n#### The @page rule\nThe page rule lets you define the '_box_' into which your content flows. \n```css\n@page {\n  /* use keywords */\n  size: A4 landscape; }\n@page {\n  /* specify dimensions */\n  size: 5in 7.5in; }\n```\n\n#### Understand the page model\nSurrounding your main content there are 16 [margin boxes](https://www.w3.org/TR/css-page-3/#margin-boxes) defined. Those can be utilized for CSS generated content.\n\n\u003ctable\u003e\n  \u003ctr\u003e\n    \u003ctd\u003etop-left-corner\u003c/td\u003e\u003ctd\u003etop-left\u003c/td\u003e\u003ctd\u003etop-center\u003c/td\u003e\u003ctd\u003etop-right\u003c/td\u003e\u003ctd\u003etop-right-corner\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003eleft-top\u003c/td\u003e\u003ctd colspan=\"3\" rowspan=\"3\"\u003e\u003ci\u003eyour content\u003c/i\u003e\u003c/td\u003e\u003ctd\u003eright-top\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003eleft-middle\u003c/td\u003e\u003ctd\u003eright-middle\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003eleft-bottom\u003c/td\u003e\u003ctd\u003eright-bottom\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003ebottom-left-corner\u003c/td\u003e\u003ctd\u003ebottom-left\u003c/td\u003e\u003ctd\u003ebottom-center\u003c/td\u003e\u003ctd\u003ebottom-right\u003c/td\u003e\u003ctd\u003ebottom-right-corner\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n\n#### Page spreads\nThere is a unique pseudo selector in print to select left and right pages (think of a book).\n```css\n@page:left {\n  margin-left: 5cm; }\n\n@page:right {\n  margin-left: 3.2cm; }\n```\nThe other ones are `:first` and `:blank`, which are pretty much self explainatory.\n\n\n#### Page breaks\nOf course you need to be able to define a page break. The older and mostly supported CSS flavor to achiveve this are `page-break-\u003cwhere\u003e`. In CSS3 this has been replaced by `break-\u003cwhere\u003e`. Morris supports both.\n```css\nh1 {\n  page-break-before: always; }\nh1, h2, h3, h4, h5 {\n  page-break-after: avoid; }\ntable, figure {\n  page-break-inside: avoid; }\n```\n\n\n#### Counters\nMorris is doing page numbers like this:\n```css\n@bottom-right-corner {\n  content: counter(page) \" of \" counter(pages); }\n```\n\nIf you need chapter and/or image numbers you could do it like this:\n```css\nbody {\n  counter-reset: chapternum figurenum; }\n\nh1 {\n  counter-reset: figurenum; }\n\nh1.title::before {\n  counter-increment: chapternum;\n  content: counter(chapternum) \". \"; }\n\nfigcaption::before {\n  counter-increment: figurenum;\n  content: counter(chapternum) \"-\" counter(figurenum) \". \"; }\n```\n\n\n#### Special strings\nOne of the weirder CSS specs is the `string-set` property. We can use that to inject CSS content but with a _document defined string_. To have a living column title you would do:\n```css\nh1 { \n  string-set: doctitle content(); }\n\n@page:right {\n  @top-right {\n    content: string(doctitle); }}\n```\n\n#### Links\nIf you intend to actually print your document you should take care of the actual link so people could go and type it in. We achieve this by setting:\n```css\na:link[href^=\"http\"]::after,\na[href^=\"http\"]:visited::after {\n  content: \" (\" attr(href) \") \";\n  font-size: 90%; }\n```\n\n\n- [Source](https://www.smashingmagazine.com/2015/01/designing-for-print-with-css/)\n\n\u003c/details\u003e\n\n\n### Testing print stylesheets\n\n\u003cdetails\u003e\n\nTesting print stylesheets might seem like a boring task involving of actual printing the page, but there is some possibility of making your live a bit easier:\n\n### Firefox\nThere is a dedicated button to switch into print view:\n\n![Firefox print view button](img/printview-firefox.png)\n\n### Chrome\nOpen the devtools, click on the three dots icon, select \"More Tools \u003e Rendering\". In this tab you can choose to \"Emulate CSS media\".\n\nPlease be aware that this will only help with changes to CSS layout, but not with fragmentation (=_laying out the individual pages_). You still need to make a PDF for checking that.\n\n\u003c/details\u003e\n\n### Other options\n- [Gutenburg](https://github.com/BafS/Gutenberg)\n- [Tufte CSS for Pandoc](https://jez.io/tufte-pandoc-css/)\n- [Pan Am](https://benjam.info/panam/)\n- [Hartija](https://github.com/vladocar/Hartija---CSS-Print-Framework)\n- [GitHub readme look-a-like](https://gist.github.com/dashed/6714393)\n- [this Gist](https://gist.github.com/killercup/5917178)\n\n### Further reading\n- [Print CSS Rocks!](https://print-css.rocks/)\n- [Article on A List Apart](https://alistapart.com/article/building-books-with-css3/)\n- [Print stylesheets in 2018](https://www.smashingmagazine.com/2018/05/print-stylesheets-in-2018/)\n- [Look at the weasyprint samples](https://github.com/Kozea/WeasyPrint/tree/gh-pages/samples)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frunxel%2Fmorris","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frunxel%2Fmorris","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frunxel%2Fmorris/lists"}