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

Multiple languages within one code block? #176

Open
karoliskoncevicius opened this issue Dec 4, 2019 · 7 comments
Open

Multiple languages within one code block? #176

karoliskoncevicius opened this issue Dec 4, 2019 · 7 comments

Comments

@karoliskoncevicius
Copy link

As far as I understand it currently it isn't possible to have multiple languages within one code block.

Maybe multimarkdown can support this by differentiating between these scenarios?

Case 1:

```lang1
foo <- bar()
```
```lang2
xxx = zzz
```

Case 2:

```lang1
foo <- bar()
```

```lang2
xxx = zzz
```

In the first case there is no empty line between the code blocks - so they will be placed within the same pre with different code classes. In the second case there is a space and so different code blocks would be in their own pre elements.

@fletcher
Copy link
Owner

fletcher commented Dec 5, 2019

This is too much of an edge case to build-in support for.

  1. I'm not convinced that a single code block should contain code in multiple languages. If there are multiple languages, then by definition there are multiple (albeit sequential) code blocks.

  2. It would break consistency with Markdown without a compelling (for most users) reason

What are you hoping to accomplish by having <code> blocks within a single <pre> block?

@karoliskoncevicius
Copy link
Author

karoliskoncevicius commented Dec 6, 2019

Thank you for responding so fast.

My particular use case is in providing code + output pairs, i.e.:

x = 1:3
mean(x)
2

Where first 2 lines are the code, and last line is the output. This is a minimal example, but it can get more complex. What I want is to provide either different text color or different background for those two contexts.

In Pandoc's case for example there is a different solution possible - Pandoc provides an option to transfer <code class="R"> up one level to <pre class="R"> which then allows for syntax highlighting like the one seen on this website: https://www.brodieg.com/2019/10/30/visualizing-algorithms/ .

After reading the multimarkdown syntax guides, I am not aware of something of this sort available in multimarkdown. Would be very happy to hear about any other possible solution that I might have missed.

@mn4367
Copy link

mn4367 commented Dec 6, 2019

This very easy to solve, just use two independent adjacent code blocks and 'stitch' them together vertically with a bit of CSS. This is exactly what is done on the site you mentioned (taken verbatim from the CSS there, so it possibly has to be tweaked):

body pre + pre:not([class]), body pre + pre.fansi {
margin-top: -19px;
}

Since you can attach multiple CSS classes to any MMD code block the possibilities are nearly unlimited.

@karoliskoncevicius
Copy link
Author

karoliskoncevicius commented Dec 6, 2019

Hello @mn4367 and thank you for the suggestion.

However, if I am not missing something - your css example assumes that the class is set for the <pre> element. Which as far as I know is not the case for multimarkdown?

I don't think I can do this for <code> classes, since they would both be within separate <pre> blocks. Unless there is some fancy css that allows to control the parent element based on the class of the child.

@mn4367
Copy link

mn4367 commented Dec 6, 2019

That's correct, I just took the example from their CSS. But nevertheless with

```javascript
console.log("never returns...");
```

```javascript second
while (true);
```

and

pre + pre {margin-top: -20px;}
.second {background-color: silver !important;}

you can make it look like one block. They use Highlight.js on the site and I tried the example above with it, it seems to work well here.

Bildschirmfoto 2019-12-06 um 12 10 53

I don't think that a class for pre is really needed (nevertheless a class could be attached with a small JS script that does its work depending on the class names of the code element).

@karoliskoncevicius
Copy link
Author

karoliskoncevicius commented Dec 6, 2019

@mn4367 thanks! I wasn't aware of the + operator in css.

However this solution still doesn't work as intended - in your example you show that the entire background of the second pre (with <code class=second> tag) is change. However in my case only the background of the code seems to be changing:

Screenshot 2019-12-06 at 9 10 20 PM

I know this is becoming a bit out of topic for this issue. But maybe you will have a quick tip about it? One possibility is probably to try turning <code> into block element with display : block;.


But I still think having native support for this would be a lot easier and would not require this complex css stylesheet. In addition it would be useful for highlighting parts of code with something like:

<pre>
<code class="cpp">
some code here
</code><code class="important">
some code in red here
</code><code class="cpp">
some not important code again
</code>
</pre>

Which in markdown then would be:

```cpp
some code here
```
```important
some code in red here
```
```cpp
some not important code again
```

And things of this nature.

@mn4367
Copy link

mn4367 commented Dec 7, 2019

I don't know which highlighting framework you are using, but I think there is a style applied to pre which has this visual effect. You'd have to inspect the CSS to see what's going wrong there.

However, I'm pretty sure this never will be added to MMD so you could use JavaScript:

document.addEventListener("DOMContentLoaded", function (_event) {

    function getNextPreElement(element) {
        let next = element.nextSibling;
        while (next && ((next.nodeType === 3) || (next.nodeType === 8))) {
            next = next.nextSibling;
        }
        if (next && (next.nodeName === "PRE")) {
            return next;
        }
        return null;
    }

    preElements = document.querySelectorAll("pre");
    let i = 0;
    while (i < preElements.length) {
        let preGroup = [];
        preGroup.push(preElements[i]);
        let nextPreElement = getNextPreElement(preElements[i]);
        while (nextPreElement) {
            preGroup.push(nextPreElement);
            nextPreElement = getNextPreElement(nextPreElement);
            i++;
        }
        if (preGroup.length > 1) {
            // classList.add isn't supported in IE 10!
            preGroup[0].classList.add("preGroup");
            while (preGroup.length > 1) {
                while (preGroup[1].firstChild) {
                    preGroup[0].appendChild(preGroup[1].firstChild);
                }
                preGroup[1].parentNode.removeChild(preGroup[1]);
                preGroup.splice(1, 1);
            }
        }
        i++;
    }

});

As far as I see this does exactly what you want to achieve, plus, it marks the pre groups with an additional class (line 28). It combines adjacent code blocks into a single one. If you have multiple code blocks which you don't want to be combined just separate them with a horizontal ruler and use

pre+hr {
  display:none;
}

or something similar to make the ruler 'disappear'.

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

No branches or pull requests

3 participants