Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Permit adding attributes to all Markdown elements #684

Open
phyllisstein opened this issue Dec 6, 2012 · 88 comments · May be fixed by jgm/pandoc-types#79
Open

Permit adding attributes to all Markdown elements #684

phyllisstein opened this issue Dec 6, 2012 · 88 comments · May be fixed by jgm/pandoc-types#79

Comments

@phyllisstein
Copy link

I'd like to suggest that Pandoc allow attributes to be attached to any Markdown element, not just code blocks. So for example, if it encountered this:

#{.main} Header

it would generate this:

<h1 class="main" id="header">Header</h1>

rather than this:

<h1 id="main-header">{.main} Header</h1>

Ditto for, say:

Header
----{.main}

...which is probably even legible enough to fit with Markdown's philosophical aversion to looking, well, marked-up.

@jamiefolson
Copy link
Contributor

FYI conversations on this topic date back 5 years:

I for one think it's surprising that nothing seems to have been done to facilitate this. I understand the desire not to pollute the syntax, but it seems like people are taking extraordinary measures to work around this limitation.

@jgm
Copy link
Owner

jgm commented Mar 16, 2013

Would you count 1.11's allowing attributes to be added to headers
as progress?

@phyllisstein
Copy link
Author

John,
I thought that was a terrific step, along with the inline_code_attributes extension. I'm looking forward to when classes and key/value pairs are implemented for headers, since the particular use case I had in mind involved setting an identifier and an onClick event.

Thanks so much for all your work on Pandoc; it's really a thing of beauty.

@jgm
Copy link
Owner

jgm commented Mar 16, 2013

+++ Daniel Shannon [Mar 15 13 18:04 ]:

John,
I thought that was a terrific step, along with the
inline_code_attributes extension. I'm looking forward to when classes
and key/value pairs are implemented for headers, since the particular
use case I had in mind involved setting an identifier and an onClick
event.

They are already implemented in 1.11!

% pandoc
# Hi {#foo .bar .baz key=val}
^D
<h1 id="foo" class="bar baz" key="val">Hi</h1>

@jamiefolson
Copy link
Contributor

I think attributes for headers are a great and wonderful thing. I also think that there are totally valid reasons for wanting to add attributes to arbitrary elements. For example, in the reports package for R, the author, possibly intimidated by haskell, resorted to a series of fragile regular expressions to try add the necessary classes and attributes to html output.

Certainly, the "fragment" class for reveal.js could and probably should be set by a new output format for pandoc, however, it's a lot harder to come up with a solution for the transition options. Both Beamer and reveal.js allow the user to configure how and when transitions occur (I don't know about all the other js templates).

Custom attributes would make it simple for reveal.js and even for beamer, the necessary script would not be complicated. Conceptually, such concepts as how and when to reveal an element feel like options rather than some new syntactic element. Alternative solutions would seem to require awkward detection and parsing of (to pandoc) literal string elements.

@luc-j-bourhis
Copy link

Imho tables are in dire need of that new syntax for attributes. It is not rare to need different tables to be displayed with different styles.

@thriveth
Copy link

thriveth commented Apr 9, 2014

And there are different LaTeX figure-environments. Allowing to set custom attributes to an image tag would mean one could more easily distinguish different kinds of figure. Other writers could simply ignore it.

@jgm
Copy link
Owner

jgm commented Apr 13, 2014

@jamiefolson: pandoc now includes a uniform syntax for transitions, which gets output as \pause in beamer and using fragment divs in revealjs. Of course, you can also just use a <div class="fragment"> in the markdown source, but this won't be portable if you decide to switch to beamer.

@luc-j-bourhis, @thriveth: You can wrap a table or figure with a div that has attributes. Are there reasons the attributes have to be on the table or image itself?

@thriveth
Copy link

@jgm I wasn't aware of that, but looking at #1242 I can see it is possible, but also witht he caveats that @blaenk mentions there.
I understand that it would be very work heavy and difficult to implement without ambiguities and messy syntax, so I second @blaenk's suggestion to implement an attribute field to the image element (because I find I almost always need to add some kind of metadata/attribute to it) and leave the rest to div/span solutions.

@mb21
Copy link
Collaborator

mb21 commented Dec 30, 2014

With image attributes underway, I could take a look at adding attributes to a few more elements if this is desired:

While the HTML writers would pass through all attributes, the others would just support the id and classes where appropriate. So beyond referencing tables and blockquotes, it would primarily enable simpler filters.

The exact markdown syntax for tables and blockquotes isn't exactly obvious, but I tend to favour the variant where the attributes have to be on their own line, trailing the actual table or blockquote (see the commonmark discussion and proposal).

@thriveth
Copy link

This is really great news!
Probably means I will soon be able to write journal article fully in
Pandoc Markdown without or almost without manual editing in LaTeX.

On 12/30/2014 01:42 PM, mb21 wrote:

With image attributes underway
#1806, I could take a look at
adding attributes to a few more elements if this is desired:

While the HTML writers would pass through all attributes, the others
would just support the |id| and |classes| where appropriate. So beyond
referencing tables and blockquotes, it would primarily enable simpler
filters.

The exact markdown syntax for tables and blockquotes isn't exactly
obvious, but I tend to favour the variant where the attributes have to
be on their own line, trailing the actual table or blockquote (see the
commonmark discussion
http://talk.commonmark.org/t/consistent-attribute-syntax/272/ and
proposal https://mb21.github.io/stmd/spec.html#extensions).


Reply to this email directly or view it on GitHub
#684 (comment).

@jamiefolson
Copy link
Contributor

This would be fantastic. Even if attributes are mostly only available in
the data model for filtering that enables a large number of currently
difficult use cases.

Jamie Olson

On Tue, Dec 30, 2014 at 8:59 AM, Thøger Rivera-Thorsen <
notifications@github.com> wrote:

This is really great news!
Probably means I will soon be able to write journal article fully in
Pandoc Markdown without or almost without manual editing in LaTeX.

On 12/30/2014 01:42 PM, mb21 wrote:

With image attributes underway
#1806, I could take a look at
adding attributes to a few more elements if this is desired:

While the HTML writers would pass through all attributes, the others
would just support the |id| and |classes| where appropriate. So beyond
referencing tables and blockquotes, it would primarily enable simpler
filters.

The exact markdown syntax for tables and blockquotes isn't exactly
obvious, but I tend to favour the variant where the attributes have to
be on their own line, trailing the actual table or blockquote (see the
commonmark discussion
http://talk.commonmark.org/t/consistent-attribute-syntax/272/ and
proposal https://mb21.github.io/stmd/spec.html#extensions).


Reply to this email directly or view it on GitHub
#684 (comment).


Reply to this email directly or view it on GitHub
#684 (comment).

@stroobandt
Copy link

This issue is also listed as item 2 on this list. (Disclaimer: I have no relation to that web site.)

@fmatheus
Copy link

Would be great if any header_attributes was supported in beamer output.
Looks like {.allowframebreaks} and .fragile by test made in 1.15.0.6.
But why not support arbitrary attributes? In particular c, noframenumbering and plain.

@jgm
Copy link
Owner

jgm commented Oct 14, 2015

+++ fmatheus [Oct 14 15 15:05 ]:

Would be great if any header_attributes was supported in beamer output.
Looks like {.allowframebreaks} and .fragile by test made in 1.15.0.6.
But why not support arbitrary attributes? In particular c,
noframenumbering and plain.

Sounds plausible to me. This just takes a small change in
the LaTeX writer.

@jgm
Copy link
Owner

jgm commented Oct 15, 2015

+++ fmatheus [Oct 14 15 15:05 ]:

Would be great if any header_attributes was supported in beamer output.
Looks like {.allowframebreaks} and .fragile by test made in 1.15.0.6.
But why not support arbitrary attributes? In particular c,
noframenumbering and plain.

I've added support for all frame attributes in commit
504bf3f

@stroobandt
Copy link

Sounds plausible to me. This just takes a small change in the LaTeX writer.

Attributes to all Markdown elements is not only useful to LaTeX and Beamer.
I personally can think of many use cases for it as XHTML classes.

@jgm
Copy link
Owner

jgm commented Oct 16, 2015

+++ Serge Y. Stroobandt [Oct 16 15 06:24 ]:

Sounds plausible to me. This just takes a small change in the LaTeX
writer.
Attributes to all Markdown elements is not only useful to LaTeX and
Beamer.
I personally can think of many use cases for it as XHTML classes.

Sure. I was responding to the (misplaced) previous comment which just
concerned Beamer attributes on headers, not to this general issue.

@jmuheim
Copy link

jmuheim commented Nov 25, 2015

@jgm:

% pandoc
# Hi {#foo .bar .baz key=val}
^D
<h1 id="foo" class="bar baz" key="val">Hi</h1>

How can an ID be applied to a link? The following doesn't work:

[Als DOCX downloaden](somewhere.html) {#download_as_docx}

@jgm
Copy link
Owner

jgm commented Nov 26, 2015

You need the very latest dev version of pandoc to apply an
ID to a link (compile from source). And you can't have a
space before the {.

+++ Joshua Muheim [Nov 25 15 14:38 ]:

[1]@jgm:
% pandoc

Hi {#foo .bar .baz key=val}

^D

Hi

How can an ID be applied to a link? The following doesn't work:
Als DOCX downloaden {#download_as_docx}


Reply to this email directly or [2]view it on GitHub.

References

  1. https://github.com/jgm
  2. Permit adding attributes to all Markdown elements #684 (comment)

@ousia
Copy link
Contributor

ousia commented Nov 28, 2015

@jgm, will all elements have attributes in Markdown?

@jmuheim
Copy link

jmuheim commented Jan 25, 2016

@jgm, which version is this? I have 1.15.2.1, which came with homebrew.

@ousia
Copy link
Contributor

ousia commented Jan 25, 2016

It comes in version 1.16.x. Latest released version is 1.16.0.2.

@elotroalex
Copy link

Any updates on this? We're trying to create a workflow that will produce a web version and a print version from the same markdown file. We're using Jekyll for web deployment. Jekyll usually plays nice with kramdown, but @mfenner has been working on a gem called jekyll-pandoc. We've been knocking our heads silly trying to decide how to handle poetry. (We're lit folks). At issue right now is the inability to handle classes at the line level so we can make the right CSS to wrap our lines nicely, etc. Kramdown handles this exceptionally well, but then we'll be giving up our workflow for pandoc | *TeX which depends on pandoc-markdown. If we can get pandoc-markdown to work well with Jekyll + poetry, we will have devised an excellent solution for a large community of editors and scholars who can now produce nice PDF's and nice websites out of the same files. We're trying at all costs to avoid to have to write filters, or divide the editing workflow into two parts. Can we get attributes at the unnumbered list line and block level, and its corollary the blockquoted unnumbered list? Or is this out with the new implementation and I missed something?

@ousia
Copy link
Contributor

ousia commented Feb 28, 2016

I think the basic issue is the following:

If Markdown is based on HTML, Markdown should have three basic attributes in all elements.

And sorry, if LaTeX cannot handle this, we should find another way of dealing with XML when using LaTeX.

@dhimmel
Copy link

dhimmel commented Apr 4, 2019

Table & Equation Attributes?

+1 for the ability to add attributes to additional markdown elements. As of Pandoc version 2.7, it appears from the docs that attributes are supports for headers, code blocks, inline code, links (includes images / figures), divs, and spans.

Attributes are not supported however for tables and equations, which I believe is causing several users trouble (see tomduck/pandoc-tablenos#11, this SO, etcetera). Setting anchors for tables and equations is one main use case that comes to mind. Currently, the pandoc-crossref, pandoc-tablenos, and pandoc-eqnos filters must use hacks to anchor tables/equations, since no id is written to the <table> element in the HTML output. Furthermore, it would be helpful to apply custom classes for styling tables.

So while universal attribute support would be great, is it possible table / equation attribute support could be added in the shorter-term, with a syntax that could be forward compatible?

@despresc
Copy link
Contributor

despresc commented Sep 7, 2020

This might be something worth picking up again (for IR support), now that the CommonMark reader has support for adding attributes to all elements.

Having a new Attr type like was proposed above would be feasible as well:

data Attr = Attr Text [Text] (Map Text Text)
-- or
data Attr = Attr
  { attrId :: Text
  , attrClasses :: [Text]
  , attrKeyVals :: Map Text Text
  }
-- The Map could be newtyped, as was suggested above

That kind of simple Attr type change would be easiest for refactoring (except for keeping the old key-value representation, but I think changing to Map is reasonable).

As for Attr use changes, I think everything in Inline and Block should get an Attr except Plain, Null, Str, Space, SoftBreak, and LineBreak. The Caption type should also get an Attr.

Possibly Plain should get an Attr? It doesn't make sense in the supported formats, but a filter writer might want it for some reason. (Though by that logic Null could get an Attr too).

Initial pandoc support would mostly consist of a lot of simple pattern-match changes, maybe aided by a conversion function to the old Attr type if that changes. Support could be added later in the HTML input and output (and elsewhere, but that's the easiest, I imagine).

@despresc
Copy link
Contributor

despresc commented Sep 7, 2020

An enhancement here is to have

data ListItem = ListItem Attr [Block]
data ListLabel = ListLabel Attr [Inline]

for the lists to use, since in LaTeX these can be labelled and referenced (list items can at least), and in HTML they are elements with the usual attributes. These seem to be the only things that are plausibly Attr-supporting but don't now have a type for Attr to be added. Well, a LineBlock could be a list of Line, I suppose.

@rickalex21
Copy link

rickalex21 commented Mar 9, 2021

UPDATE: This is more of a hack but I figured it out and it works. I will post so that it will help someone else in the future. Hopefully, in the future there's an easier way to add classes to elements in pandoc other than just a few. I don't know a lot of lua, so if anyone knows of an easier way feel free to comment.

local List = require 'pandoc.List'
function Para(el)
    local classes = {coffee = '{.tip}',warn = '{.warn}'}
    for k,v in pairs(el.content) do
        text = v.text
        for name,class in pairs(classes) do
            if class == text then
                el.content[k].text = ''
                local p = List:new{}
                p:extend({pandoc.RawBlock('html', '<p class="'.. name .. '">')})
                p:extend({pandoc.Plain(el.content)})
                p:extend({pandoc.RawBlock('html', '</p>')})
                return p
            end
        end
    end
end

Has this been resolved? I need to change a class on paragraphs depending on if a word is found in the paragraph. Unfortunately, according to the docs Para only takes one argument which is content. Span takes 2, might need to wrap it with span. Not sure if I can hack this with the following?

 return pandoc.RawBlock('html','<p>'..element.content..'</p>')

Probably not, since I more than likely have to loop and extract everything out of content. Seems like a lot of work just to insert a class into a paragraph. I can easily do this in hugo with {.myclass} after the paragraph. Hopefully this will be adopted by pandoc.

OR wrapping it like in this example:

function Para(el)
  content = el.content
  attr = pandoc.Attr("", {".myclass"})
  return pandoc.Para(pandoc.Span(content, attr))
end

@gusbemacbe
Copy link

UPDATE: This is more of a hack but I figured it out and it works. I will post so that it will help someone else in the future. Hopefully, in the future there's an easier way to add classes to elements in pandoc other than just a few. I don't know a lot of lua, so if anyone knows of an easier way feel free to comment.

local List = require 'pandoc.List'
function Para(el)
    local classes = {coffee = '{.tip}',warn = '{.warn}'}
    for k,v in pairs(el.content) do
        text = v.text
        for name,class in pairs(classes) do
            if class == text then
                el.content[k].text = ''
                local p = List:new{}
                p:extend({pandoc.RawBlock('html', '<p class="'.. name .. '">')})
                p:extend({pandoc.Plain(el.content)})
                p:extend({pandoc.RawBlock('html', '</p>')})
                return p
            end
        end
    end
end

Has this been resolved? I need to change a class on paragraphs depending on if a word is found in the paragraph. Unfortunately, according to the docs Para only takes one argument which is content. Span takes 2, might need to wrap it with span. Not sure if I can hack this with the following?

 return pandoc.RawBlock('html','<p>'..element.content..'</p>')

Probably not, since I more than likely have to loop and extract everything out of content. Seems like a lot of work just to insert a class into a paragraph. I can easily do this in hugo with {.myclass} after the paragraph. Hopefully this will be adopted by pandoc.

OR wrapping it like in this example:

function Para(el)
  content = el.content
  attr = pandoc.Attr("", {".myclass"})
  return pandoc.Para(pandoc.Span(content, attr))
end

Hello @rickalex21, there is a small problem. I have a class containing a hyphen, i.e., {.first-letter}. I know I should write first_letter = {.first-letter}, but I prefer <p class="first-letter"> instead of <p class="first_letter">.

@memeplex
Copy link

memeplex commented Feb 2, 2024

I notice there is the non-default extension-attributes (https://pandoc.org/MANUAL.html#extension-attributes):

Allows attributes to be attached to any inline or block-level element when parsing commonmark.

Doesn't it address this issue?

@jgm
Copy link
Owner

jgm commented Feb 3, 2024

That extension works with commonmark (and gfm and commonmark_x) but not pandoc's markdown.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging a pull request may close this issue.