Support for Markdown in assets/logs/etc

What do folks think about adding support for Markdown in textarea fields in farmOS records?

This would allow you to easily create numbered/bulleted lists, bold/italic formatting, links, etc in notes and other textarea fields.

This is something I’ve wanted personally for a long time. In fact, I added it briefly in farmOS v1, but was later dissuaded and decided to remove it because of some uncertainty surrounding the v2 rewrite.

Historical context:

The idea came up again on yesterday’s dev call, so I’m opening this topic to explore the idea again, and see what others think.

3 Likes

That would be awesome, I’d say

1 Like

I’m testing this module: https://www.drupal.org/project/markdown

Along with this parser: https://commonmark.thephpleague.com/ (the module has a plugin system for using different parsers, but recommends league/commonmark).

I started a draft pull request here: Add support for Markdown in default text format by mstenta · Pull Request #1072 · farmOS/farmOS · GitHub

1 Like

Notes from my testing:

Below is a quick test using all the default module configurations (in a notes field on a log).

Input:

This is a test of some markdown...

Test that newlines are preserved.

Test that URLs convert to links: https://farmOS.org

> Test blockquote.

*Test italics*

**Test bold**

~~Test strikethrough~~

[Test link](/log/1)

- Test unordered list 1
- Test unordered list 2
- Test unordered list 3

1. Test ordered list 1
2. Test ordered list 2
3. Test ordered list 3

**HTML filtering tests:**

</body></html>

**XSS filtering tests:**

<script>alert('test');</script>

> hello <a name="n"
> href="javascript:alert('xss')">*you*</a>

<blockquote>
 <p>hello <a name="n"
 href="javascript:alert('xss')"><em>you</em></a></p>
</blockquote>

[some text](javascript:alert('xss'))

Result:

It appears that URLs are not being converted to links automatically and strikethrough formatting doesn’t work. HTML tag and XSS filtering appear to be working, although we may want to add more tests of this…

This is what the same input looks like currently (before swapping out our current input filters with markdown):

Differences:

  • URLs are automatically converted to links.
  • Markdown isn’t formatted (obviously).

Also worth noting, this is what the “Notes” field looks like before/after…

Before:

After:

Sort of good and sort of bad. On the one hand it’s nice to simplify and hide the bulleted list of formatting tips. But on the other hand, those can be helpful.

The little black markdown icon in the bottom right links to the same place as the old “About text formats” link (/filter/tips). Below are screenshots of that page before/after…

Before:

After:

The “[More info]” link in the last screenshot links to https://www.drupal.org/docs/contributed-modules/markdown

For additional context: farmOS installs with two text formats: default (provided by farmOS) and plain_text (provided by Drupal).

The idea behind this, in Drupal generally, is that different user roles might have access to use different formats (eg: a blog editor might have more flexibility than an anonymous user leaving a comment). If a user has access to multiple formats, they will be able to select the one they want in a dropdown under the text field.

In farmOS, we only use the “Default” format and there is no option to use “Plain text”, so it’s a bit confusing that we show it in /filter/tips. We could consider removing that… sort of a separate (but related) question…

Either way, it does feel like /filter/tips loses a lot of value after changing to markdown. I also don’t like that it links to a drupal.org page for the module’s documentation. Sending a farmer there isn’t very helpful. :thinking:

Notably, the league/commonmark library actually includes two parser choices:

The first one (not “GitHub Flavored Markdown”) is installed by default.

This quick start guide explains the options: https://www.drupal.org/docs/contributed-modules/markdown/quickstart-guide

If we want to use GFM, and/or change any of the default parser settings, we’ll need to add a hook_install() implementation to the farm_format module to do that.

Looks like this is one of the configuration options in the parser… it’s just disabled by default.

Skimming CommonMark Spec vs GitHub Flavored Markdown Spec, these seem to be the main things that GitHub Flavored Markdown add to the CommonMark spec:

It seems to me like GitHub Flavored Markdown would be a good default for farmOS.

So since the current farmos default text format is filtered html,
for backward compatibility we’ll have to default to selection of the current text format (which should be labeled something like “Filtered HTML”) and add the markdown text format, which gives the editor this (new to them) drop-down under the field; example:

I tested my use case (headings with hierarchical/outline/legal numbering) with GFM markdown, which took some custom css, but what I’m after does work, see attached html + css file (rename removing .txt).
Note that I attempted to contain the css with an <article> element just for this example; farmos implementation might need .region-content or a field specific class. I think this css approach is useful for both html and md fields.

pandoc gfm to html5 output.html.txt (7.2 KB)

If you’re discussing such a document, it’s really handy to say, “Let’s talk about item 3.1.2.”

Also note the discussion of preventing use if h1 in user editable fields, per w3c. This should apply to both html and md fields.

I didn’t look into the strikethrough problem, but strikethrough is very handy to indicate recently removed items in a how-to, so people know that you intentionally removed something, and they should not cruise through the usual steps on auto-pilot. :slight_smile:

1 Like

Actually, it’s not. The “Filtered HTML” format that is in your screenshot is from a default Drupal installation. We don’t use that. We provide our own, and just call it “Default”. This way, we simplified things by taking an opinionated approach in farmOS and said “we’ll only have one text format”.

So, I’m proposing just enabling Markdown parsing on our existing “Default” text format - not adding a separate one alongside it. Thus, from a user perspective it will all work the same as before, except now Markdown formatting will be parsed into HTML automatically. No need to select a different format from a dropdown (or understand what any of that means).

@rmattb Giving this some more thought… with Markdown you don’t use <ol> and <li> tags directly, so for numbered lists you have to type out the numbers you want anyway, which means you can achieve the “hierarchical/outline/legal numbering” you’re describing… it just requires manually typing them. :slight_smile:

For example (this forum uses Markdown too):

  1. First item
    1.1. First sub item
    1.2. Second sub item
  2. Second item
  3. Third item

Adding additional CSS, like you describe, is only necessary if you want to write your lists in HTML (using <li>) tags. But with Markdown you don’t need to do that. So maybe we don’t need anything else?

This seems to work well!

The only problem I ran into is the CommonMark GFM parser doesn’t seem to convert headings (eg: ## Heading => <h2>Heading</h2). The CommonMark parser does, so it seems to be a bug. I opened an issue to investigate: https://www.drupal.org/project/markdown/issues/3580640

I found a workaround for the header bug, and pushed all my current work to the PR: Add support for Markdown in default text format by mstenta · Pull Request #1072 · farmOS/farmOS · GitHub

Ready for review!

For future reference, here is a larger test input I have been using, followed by what it looks like before and after making this change…

Input:

This is a test of some markdown...

# Test H1

## Test H2

### Test H3

#### Test H4

##### Test H5

###### Test H6

Test that newlines are preserved.

Test that URLs convert to links: https://farmOS.org

> Test blockquote.

*Test italics*

**Test bold**

~~Test strikethrough~~

[Test link](/log/1)

- Test unordered list

1. Test ordered list

**HTML filtering tests:**

</body></html>

**XSS filtering tests:**

<script>alert('test');</script>

> hello <a name="n"
> href="javascript:alert('xss')">*you*</a>

[some text](javascript:alert('xss'))

**Raw HTML tests:**

<a href="https://farmOS.org">Test link</a>

<img src="http://localhost/profiles/farm/modules/core/ui/theme/logo.png" />

<em>Test italics</em>

<strong>Test bold</strong>

<del>Test strikethrough</del>

<cite>Test citation</cite>

<blockquote>Test blockquote</blockquote>

<code>Test code</code>

<ul>
  <li>Test unordered list</li>
</ul>

<ol>
  <li>Test unordered list</li>
</ol>

<h1>Test H1</h1>

<h2>Test H2</h2>

<h3>Test H2</h3>

<h4>Test H4</h4>

<h5>Test H5</h5>

<h6>Test H6</h6>

Before:

After:

Oh ok, that’s much simpler. Sounds good.

A post was split to a new topic: Markdown list formatting CSS enhancements

@rmattb I spun off your last list-formatting CSS comment to it’s own topic, so we can discuss that separately from Markdown support more generally: Markdown list formatting CSS enhancements