php-markdown icon indicating copy to clipboard operation
php-markdown copied to clipboard

Add support for classes on paragraphs

Open tobiastom opened this issue 10 years ago • 18 comments

Is there a special reason why paragraphs cannot define classes? This would be pretty nice to define layouts, even in markdown.

/cc @kburton Referencing you because just just implemented it for tables, maybe you know your way to easily implement this one as well…

tobiastom avatar Mar 06 '14 15:03 tobiastom

I'm sure a syntax for that could be added, but paragraph classes are pretty easy to define already:

{.some-class .proposed-syntax}
A paragraph of text.

vs

<p class="some-class" markdown="1">
  A paragraph of text.
</p>

When you compare the code for tables, the ability to add a class via markdown attributes makes a world of difference:

Some | Basic | Table {.table .table-striped}
-----|-------|------
a    | b     | c
d    | e     | f

vs

<table class="table table-striped">
  <thead>
    <tr>
      <th>Some</th>
      <th>Basic</th>
      <th>Table</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>a</td>
      <td>b</td>
      <td>c</td>
    </tr>
    <tr>
      <td>d</td>
      <td>e</td>
      <td>f</td>
    </tr>
  </tbody>
</table>

I was somewhat forced into adding the table attributes because it proved very difficult for non-technical users to maintain syntactic correctness while creating or editing a table like that.

kburton avatar Mar 06 '14 18:03 kburton

I've been following requests for classes and id attributes with interest. For some constructs, like headers, it's pretty obvious what the syntax should be. But I've restrained myself from implementing something for paragraphs until I've found a satisfying solution for other constructs, mainly lists, out of fear it'd become conflicting later. I'm a little concerned by attributes attached to lists, list items, and paragraphs all being ambiguous with each other.

For instance, where should you put your attributes and what should it do in the following case?

*   list item

*   list item {.classA}
    {.classB}
{.classC}

I'd tend to think classA should apply to the paragraph, classB to the item, and classC to the list as a whole. But that doesn't look good; Markdown is supposed to be readable so I'd like to keep the gibberish of HTML attributes from interfering with reading the text version.

Maybe the rule should be that the attributes must be before the element it qualifies, but that seems quite worse:

{.classA}
*   {.classB}
    {.classC} list item

*   list item

Here classA is for the list, classB for the item, and classC for the paragraph.

Rather, I think should mix things up and say that lists attributes comes before while item and paragraph attributes after:

{.classA}
*   list item {.classB}
    {.classC}

*   list item {.classD}
    {.classE}

The paragraph class should be on the same line as the paragraph, while the item class should be on a separate line... that's for cases where a list item contains block-level content (such as paragraphs). Other cases are easier to disambiguate and can be more lax with whitespace.

I don't look forward to documenting that though.

michelf avatar Mar 06 '14 19:03 michelf

I think I would go with the "before" rule.

{.lala}
this my my paragraph with the lala class
{.lala}
- Thus list
- will have the
- class lala

Regarding list items, I have some idea, but I don't know if that would break anything:

-{.lala} this li will get the class lala
-{.foo} this one will get the class foo

Also, this concept could be used for DLs.

tobiastom avatar Mar 07 '14 11:03 tobiastom

@kburton Regarding <p class="some-class" markdown="1"> I tend to agree, still… for me it feels wrong to have HTML inside markdown.

tobiastom avatar Mar 07 '14 11:03 tobiastom

@tobiastom The reason Markdown allows HTML is so you can do everything you can do with HTML without having to reinvent a syntax for every HTML feature. It's perfectly fine to use HTML within Markdown.

The problem I'd like to solve is that sometime you need to give up the Markdown syntax entirely because you need a style hook on something. Adding a class to a list or a table forces you to rewrite the entire thing to HTML, which is quite inconvenient. I'm less concerned about mere paragraphs, usually I wrap them in a <div class="some-class" markdown="1">.

As for list items, I'd like to have single-line items look like this:

- good banana                 {.good}
- bad orange                   {.bad}
- good apple                  {.good}
- so-so blueberry            {.so-so}

Here the class can be put on the side, far from the content itself, making it look like a margin annotation. That's why I'm thinking about putting the attributes at the end. It already works like this for headers, and it'd look good for terms in definition lists too. It just doesn't look as good for block-level content.

michelf avatar Mar 07 '14 11:03 michelf

It could depend on how strict people are with their text formatting. I've gotten into the habit of chopping my paragraphs into smaller chunks for legibility in the raw Markdown. As long as there's some space to push the ID/class declaration it isn't too distracting.

# A Study In Scarlet

## PART I.

(Being a reprint from the reminiscences of John H. Watson, M.D., late of the Army 
Medical Department.)

1.  ### Mr. Sherlock Holmes

    In the year 1878 I took my degree of Doctor of Medicine of the 
    University of London, and proceeded to Netley to go through 
    the course prescribed for surgeons in the army. Having completed 
    my studies there, I was duly attached to the Fifth Northumberland 
    Fusiliers as Assistant Surgeon. The regiment was stationed in 
    India at the time, and before I could join it, the second [...]

    The campaign brought honours and promotion to many, but for me 
    it had nothing but misfortune and disaster. I was removed from my 
    brigade and attached to the Berkshires, with whom I served at 
    the fatal battle of Maiwand. There I was struck on the [...]            {.randomClass}

2.  ### More content

    Worn with pain, and weak from the prolonged hardships which 
    I had undergone, I was removed, with a great train of wounded 
    sufferers, to the base hospital at Peshawar. Here I rallied, and had 
    already improved so far as to be able to walk about the [...]

p.s. I tend to agree on the adding classes/IDs to every possible element to be overkill.

vagari avatar Mar 07 '14 14:03 vagari

I really like the right indent style.

tobiastom avatar Mar 10 '14 18:03 tobiastom

The single line list items with the attributes on the right works for me. I think that trying to add attribute support generically to all elements will risk making documents less readable and make the syntax more difficult to write and understand.

In any case, I think the attributes look better before the block in block level elements rather than after.

kburton avatar Mar 12 '14 14:03 kburton

It's worth considering how Maruku and especially kramdown go about this:

http://kramdown.gettalong.org/syntax.html#inline-attribute-lists http://maruku.rubyforge.org/proposal.html

louquillio avatar Mar 12 '14 14:03 louquillio

I think the right margin style is a good argument for putting the attributes at the end. Attributes for headers follow the header, same thing for images and links. Also, that's what Kramdown and Maruku seems to do in other places (thanks @louquillio for those links), even though the syntax is slightly different (it requires a colon).

Now I need to figure out a way to explain what happens with paragraphs nested in blockquotes, lists and other things and disambiguate which attributes applied on which of those nested elements. Perhaps something inside the attribute braces could do that...

* item

* item                 {ul#id}

That's just a vague idea. Note that in the above example we need to disambiguate between the p, the li and the ul elements.

michelf avatar Mar 13 '14 15:03 michelf

The right margin syntax worked for inline elements. The kramdown syntax looks nice for block level elements, it allows an attribute directly before or after the block-level element. There has to be a form of attribute precedence, e.g. inline-element preceding-block following-block. Would that work?

Example:

{.list-class}
- good banana                 {.good}
- bad orange                   {.bad}
- good apple                  {.good}
- so-so blueberry            {.so-so}
Testing | Basic | Table
--------|-------|------
a       | b     | c
{.table-class}
Testing | Basic | Table
--------|-------|------
a       | b     | c
{.table-class}
A paragraph with text

markseuffert avatar May 27 '14 14:05 markseuffert

Something I would like to solve are multi column page layouts. For non-technical users it's hard to wrap stuff in <div class="some-class" markdown="1"> HTML-code. Maybe there's a good way for telling Markdown to generate divs? How about paragraphs with kramdown syntax (attribute in preceding-block or following-block) to generate divs?

Example:

{.column-features-class}
No more databases, comment moderation, or pesky updates.

{.column-features-class}
Markdown (or Textile), Liquid, HTML & CSS go in. Static sites come out.

{.column-features-class}
Categories, pages, posts, and custom layouts are all first-class citizens here.

Just an idea.

markseuffert avatar Jun 03 '14 14:06 markseuffert

I don't know. The approach I've taken is to create a template system, where the user chooses the layout that they want and then is prompted to complete the appropriate number of content blocks (and upload the appropriate number of images). This is a lot easier for the end user to understand than trying to add semantic mark up to blocks.

The image below shows the template selection widget, but new templates can be created dynamically by a user with the appropriate permissions.

templates

kburton avatar Jun 03 '14 19:06 kburton

I'm seconding this feature request. My users cannot possibly wrap their head around any HTML, and that's why I used markdown in the first place. But without the ability to define basic styles on block-level elements, it becomes almost useless in my particular case.

Right now I style headers as general block contents, which is super hacky in CSS. For instance:

// Markdown:
# Needs styling {.style}

// CSS:
h1[class] // Remove styling
{
    font: inherit;
    margin: 0;
}

h1.style
{
    // My custom styles
}

Please do consider the kramdown syntax. I would have moved to this library already if it was somehow possible to use it in PHP...

lazlo-bonin avatar Jul 30 '14 21:07 lazlo-bonin

I have implemented it in way similar to kramdown

some text paragraphs
{:.some-class .other-class #theid}

I didn't study the code, but quickly find a place to implement it, inside the formParagraphs method. I really needed this feature and maybe someone else is interested on this hack while the library give a final solution.

https://github.com/kanzeon/php-markdown/commits/lib

rhuelga avatar Oct 28 '14 12:10 rhuelga

What about having a "fenced" DIV ? We simply need similar with the syntaxe used for <code> blocks...

I suggest

::::::::::::::::::::::::::::::::::{ .myClass #myId} my div ::::::::::::::::::::::::::::::::::

mdan312 avatar Jan 23 '15 21:01 mdan312

I open an new ticket to debate about that suggestion : #191

mdan312 avatar Jan 23 '15 21:01 mdan312

I think we don't need fenced elements. I just think we need something that assigns attributes or classes to "the next upcoming element" – whatever that element might be.

tobiastom avatar Feb 28 '15 09:02 tobiastom