pandoc / lua-filters

A collection of lua filters for pandoc
MIT License
600 stars 165 forks source link

Adding a md to bootstrap filter #239

Closed fxpar closed 1 year ago

fxpar commented 2 years ago

Is someone working on a Lua filter to convert md to bootstrap?

I thought of something like this: https://github.com/fxpar/Pandoc-Lua-Markdown-Bootstrap

fxpar commented 2 years ago

Trying a fork https://github.com/fxpar/lua-filters/tree/master/md-to-bootstrap if someone wants to work on this

mfhepp commented 2 years ago

Personally, I would not put it into a Lua-Filter, but instead use a custom output template for HTML.

Here are some related projects:

https://git.tpi.uni-jena.de/dg/notes/-/tree/main/md/pandoc-bootstrap-template https://github.com/ashki23/pandoc-bootstrap (I tweaked this for my personal needs)

You could also try to reuse the work from the Quarto project, which internally uses Pandoc, afaik.

fxpar commented 2 years ago

Thanks @mfhepp Unfortunately these projects succeed in including the markdown content into a bootstrap environment (with navbar, sidebar, toc...) , but they do not convert the content into bootstrap components. What I am looking for is a way to turn the content into cards, carousel, accordion...

A Lua filter seemed a good option to achieve this. Here is where I got with lots of help from @tarleb : https://github.com/fxpar/lua-filters/tree/master/md-to-bootstrap#header-block-jumbotron

mfhepp commented 2 years ago

Manubot does this for the HTML output, see here.

For examples of the resulting HTML, see the Manubot catalog or e.g. this one here.

While the standard Manubot output is not based on Bootstrap, you could follow the same route.

You might want to use a filter for adding Bootstrap CSS classes to Pandoc elements or to modify some aspects of the document. But I would strongly advise not to bypass Pandoc for creating the HTML output.

By the way, AFAIK, all additional classes from Markdown will be passed to the resulting HTML elements, so you can actually specify Bootstrap classes directly in Markdown.

As said, https://github.com/ashki23/pandoc-bootstrap is basically a skeleton for your needs, IMO.

fxpar commented 2 years ago

Thank you very much @mfhepp for pointing me in direction of Manubot, which I didn't know. I will investigate the possibilities. In the meanwhile, here is a demo of the conversion for teachers. You can see how quickly a quiz can be created. Thanks again for the link.

fxpar commented 2 years ago

Here is a first version of the Markdown to Bootstrap filter. Still a lot of work to do, but the first result looks really promising: https://github.com/fxpar/markdown-to-bootstrap-pandoc-lua-filter Thanks a lot to @tarleb for his coding help and @mfhepp for the advice.

tarleb commented 2 years ago

Very cool! I've tweeted about it to get the word out.

mfhepp commented 2 years ago

Thanks for your effort! However, I still think that the approach you take can be made much more sustainable, in particular for Markdown documents that shall be converted to multiple output formats (e.g. Web page, lecture notes, Beamer slides).

Basically, I am not convinced that replacing the fenced divs by HTML inline directly is a good technique.

Your approach works as a quick hands-on solution, but it has caveats:

  1. Your dedicated new HTML template has to be kept in sync with changes in the official Pandoc HTML template and the HTML writer; avoid that if possible by rather using
    --include-in-header
    --include-before-body
    --include-after-body

    either in a defaults file or in the YAML meta-data of the document or a meta-data file. The WWW is full of historical tweaks of the Pandoc HTML and LaTeX templates that fixed a problem back then but won't work with the current Pandoc version.

  2. The Markdown will be unavailable or not look nice in other output formats without another filter. Ideally, a format-specific feature will not hurt standard output formats. This will make your content files much harder to maintain and reuse (e.g. for a later textbook, Beamer slides, ...).
  3. The manual generation of HTML snippets may break when handling special characters, Unicode, unexpected content, etc. That is similar to generating XML with print statements - it works at first, but will bite you later on.
  4. The order of executing filters will matter, because you the original Markdown will not be available for subsequent filters (think of spell-checkers etc.).

Note that is is straightforward in Pandoc Markdown to attach CSS classes and attributes to fenced divs in a way that they will be

Just add curly brackets to the opening fence and add a dot in front of class names.

For instance, you can directly use Bootstrap Alerts like so:

:::{.alert .alert-primary role="alert"}
A simple primary alert—check it out!
:::

:::{.alert .alert-secondary role="alert"}
A simple secondary alert—check it out!
:::

:::{.alert .alert-success role="alert"}
A simple success alert—check it out!
:::

:::{.alert .alert-danger role="alert"}
A simple danger alert—check it out!
:::

:::{.alert .alert-warning role="alert"}
A simple warning alert—check it out!
:::

:::{.alert .alert-info role="alert"}
A simple info alert—check it out!
:::

:::{.alert .alert-light role="alert"}
A simple light alert—check it out!
:::

:::{.alert .alert-check role="alert"}
A simple dark alert—check it out!
:::

and as long as your HTML template contains, or is being told to contain a link element to Bootstrap, like so

<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" ...>

then the elements will come out properly without a much tweaking of the HTML template or hard-wired Markdown-to-HTML conversions.

Pandoc will generate HTML like so

<div class="alert alert-primary" role="alert">
<p>A simple primary alert—check it out!</p>
</div>
<div class="alert alert-secondary" role="alert">
<p>A simple secondary alert—check it out!</p>
</div>
<div class="alert alert-success" role="alert">
<p>A simple success alert—check it out!</p>
</div>
<div class="alert alert-danger" role="alert">
<p>A simple danger alert—check it out!</p>
</div>
<div class="alert alert-warning" role="alert">
<p>A simple warning alert—check it out!</p>
</div>
<div class="alert alert-info" role="alert">
<p>A simple info alert—check it out!</p>
</div>
<div class="alert alert-light" role="alert">
<p>A simple light alert—check it out!</p>
</div>
<div class="alert alert-check" role="alert">
<p>A simple dark alert—check it out!</p>
</div>

See attached image.

alerts
fxpar commented 2 years ago

hi @mfhepp Thank you taking time to write a detailed answer.

POC

Indeed, my filter is more a "proof of concept" to show that teachers, without any html or css knowledge, can easily output complex bootstrap material like tabs, carousel and accordion for elearning production. I hope that some people with better understanding of Lua will undertake the challenge of rewriting the code in some efficient way, especially to easily maintain it and keep up with pandoc evolution. Unfortunately, this is beyond my competences... I already bothered Tarleb enough.

Expert subject matter on ipads

The use of complex syntax like curly brackets, dots, double quotes, equal sign, in front of attributes is, for some people I work with (subject matter experts in HR, law or litterature), far out of reach and should be avoided as much as possible. Often they type or update content using ipads or phones, and the accessibility of characters like square brackets or curly brackets make writing very error prone. Even typing the code for an image in markdown is a pain on a phone, requiring to get the url in one screen, copying it, coming back to the editor which often reloads and loses previous typing, finding the exclamation mark...

Simplification

The repetition of attributes in bootstrap (three times "alert" in the html / css) should also be handled by the filter to relieve the typing. That's why I opt for ::: success rendering as <div class="alert alert-success" role="alert"> without the necessity for content editor to know anymore about bootstrap than the type of the div.

The concern you express about unicode or content breaking the output is of course what any programmer dreads when input is not sanitized enough... for now I don't have solution, and I hope someone will answer to get some directions on this.

Thank you again for your engagement and support in my project. F

mfhepp commented 1 year ago

I appreciate your effort, but frankly “Premature optimization is the root of all evil” - hard-coding functionality that circumvents the official architecture will make your solution brittle and hard to maintain. If you are aiming at a quick fix, that's fine. For a lasting contribution, it will backfire sooner or later.

If you want to free users from knowing the Bootstrap classes etc., then why not simply write a LUA filter that replaces simpler, custom class identifiers to the required ones for Bootstrap, and then pass all further processing to the regular Pandoc workflow and components (HTML exporter etc.)?

Like so

User writes:

:::{.bootstrap_alert}
A simple primary alert—check it out!
:::

or, simpler (when you do not need additional classes or attributes attached to the fenced div):

::: bootstrap_alert
A simple primary alert—check it out!
:::

Filter will translate to:

:::{.alert .alert-primary role="alert"}
A simple primary alert—check it out!
:::
tarleb commented 1 year ago

I've added the filters and template mentioned here to https://github.com/pandoc-ext/info, the repository where I'll collect this kind of information for now.

Closing this issue, as we won't add new filters to this repository.