Giter VIP home page Giter VIP logo

pandoc-emphasize-code's Introduction

pandoc-emphasize-code

A Pandoc filter for emphasizing code in fenced blocks.

Usage

Often when working with code examples in documentation, printed or web hosted, or in presentation slideshows, you might want to emphasize parts of a code snippet.

You can get away with manually writing the target markup, in LaTeX or raw HTML, but if you want to render the same document in multiple output formats, this gets really tedious. Also, having to write the markup by hand can be error prone.

This filter lets you specify ranges of a code block to emphasize, and have the filter generate the appropriate markup for you. It recognizes code blocks with the emphasize attribute present:

```{.haskell emphasize=2-2,3:3-3:12}
myFunc = do
  newStuffHere
  andThisToo notThis
  notSoRelevant
```

The rendered output looks like this (if you’re on GitHub, see the rendered output online):

myFunc = do
  newStuffHere
  andThisToo notThis
  notSoRelevant

Currently, the following output formats are supported:

  • HTML (html and html5)
  • LaTeX (latex and beamer)
  • GitHub-Flavored Markdown (markdown_github)
  • RevealJS (revealjs)

Syntax

The value of the emphasize attribute is a comma-separated list of ranges. A range consists of either two positions or two line numbers, separated by a dash. A position consists of a line number and a column number, separated by a colon.

The syntax can be described in EBNF, like so:

line number     = natural number;
column number   = natural number;
position        = line number, ":", column number;
range           = position, "-", position
                | line number, "-", line number;
ranges          = range, { (",", range) };

(* definition of natural number excluded for brevity *)

There must be at least one range in the comma-separated list. A range can span multiple lines. For ranges composed of line numbers, the start and end columns are assumed to be the first and last column on that line.

Rendering to HTML

The code block above would render HTML output like the following (lines broken for readability):

<pre class="haskell"><code>myFunc = do
<mark class="block">  newStuffHere</mark>
  <mark class="inline">andThisToo</mark> notThis
  notSoRelevant</code></pre>

When rendering to html5 or revealjs, the emphasized ranges are wrapped in <mark> tags. The default browser styling is black text on yellow background, but can be customized with CSS:

code mark {
  background-color: black;
  color: white;
}

The html and markdown_github output formats use <em> tags instead of <mark> tags. By default, <em> tags are rendered in italic type, but can be customized with CSS:

code em {
  font-weight: bold;
  font-style: normal;
}

If you want to achieve the same “entire line” highlighting effect seen in the above examples, you’ll also want to add these styles:

pre > code {
  position: relative;
  display: inline-block;
  min-width: 100%;
  z-index: 1;
}

mark.block::after {
  content: "";
  position: absolute;
  background-color: yellow;
  z-index: -1;

  /**
   * Adjust these sizes to work with your code blocks.
   * For example, you can set left & right to be negative
   * if you have padding on your code blocks.
   */
  left: 0;
  right: 0;
  height: 1.5rem;
}

NOTE: There is no additional syntax highlighting when emphasizing code and rendering to HTML, as there is no way to use Pandoc’s highlighter and embed custom HTML tags. You can usually recover language-based syntax highlighting with a JavaScript syntax highlighter running in the browser on page load (for example: highlight.js).

Rendering with LaTeX

When rendering using LaTeX, two things are required:

  • The listings package needs to be included.
  • You need to define a CodeEmphasis and CodeEmphasisLine command, styling the emphasized code in lstlistings.

If you’re not using a custom LaTeX template, you can use the YAML front matter in a Markdown source file to add the requirements:

header-includes:
  - \usepackage{listings}
  - \lstset{basicstyle=\ttfamily}
  - \newcommand{\CodeEmphasis}[1]{\textcolor{red}{\textit{#1}}}
  - \newcommand{\CodeEmphasisLine}[1]{\textcolor{red}{\textit{#1}}}

NOTE: When rendering as Beamer slides, any frame including an emphasized block must be marked as fragile:

## My Slide {.fragile}

```{.haskell emphasize=2:3-2:14,3:3-3:12}
myFunc = do
  newStuffHere
  andThisToo notThis
  notSoRelevant
```

Regular Highlighting

You can still use regular Pandoc highlighting (the skylighting library):

``` {.haskell}
myFunc :: The Type -> Signature
myFunc = do
  newStuffHere
  andThisToo notThis
  notSoRelevant
```

It gives you all the nice colors:

myFunc :: The Type -> Signature
myFunc = do
  newStuffHere
  andThisToo notThis
  notSoRelevant

The drawback is that you have two different highlighting systems now, one for emphasized code, one for regular code blocks.

Install

Executables for Linux and macOS are available in the Releases page.

From Hackage

If you’d rather install using cabal or stack, you can use the following command:

cabal install pandoc-emphasize-code

The package is available at Hackage.

Build

Requirements:

To install from sources, run:

git clone [email protected]:owickstrom/pandoc-emphasize-code.git
cd pandoc-emphasize-code
stack setup
stack install

Run

If you have installed from sources, and you have ~/.local/bin on your PATH, you can use the filter with Pandoc like so:

pandoc --filter pandoc-emphasize-code input.md output.html

Changelog

  • 0.3.0
    • Bump pandoc-types to >= 1.20
  • 0.2.4
    • Allow full lines to specified, without any column information
    • Escape special LaTeX characters in emphasized code chunks
  • 0.2.3
    • Allow single-position range, i.e. one where the start and end is the same position, which is needed to emphasize a single character.
  • 0.2.2
    • Revert to use newlines in HTML pre tags
    • Use default Setup.hs script
  • 0.2.1
    • Support revealjs output
    • Use <mark> for HTML5 and RevealJS, <em> for HTML and GFM
  • 0.2.0
    • Use Lucid to render HTML, fixes issue #1
  • 0.1.1
    • Restructured modules
    • Separated pretty printer
    • Better error messages
    • Improved validation
    • Documentation styling improvements
  • 0.1.0
    • First release
    • Support for multiple ranges
    • Rendering support for HTML, Markdown, and LaTeX

License

Copyright 2017 Oskar Wickström

Mozilla Public License Version 2.0

pandoc-emphasize-code's People

Contributors

jez avatar owickstrom avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

pandoc-emphasize-code's Issues

CodeEmphasisLine called on every word in a line instead of the whole line

Here is my input file, example.md, only a slight variation on doc example from the docs:

---
header-includes:
  - \usepackage{listings}
  - \lstset{basicstyle=\ttfamily}
  - \newcommand{\CodeEmphasis}[1]{\textcolor{red}{\textit{#1}}}
  - \newcommand{\CodeEmphasisLine}[1]{\colorbox{yellow}{#1}}
---

# My Slide {.fragile}

```{.haskell emphasize=2:3-2:14,3:3-3:12,4-4}
myFunc = do
  one two three
  four five six
  seven eight nine
  ten eleven twelve
```

When I run pandoc --filter pandoc-emphasize-code --to beamer example.md --output example.pdf

Instead of one solid yellow background I get irregularly shaped backgrounds around each word.

When I run pandoc --filter pandoc-emphasize-code --to beamer example.md

I get the following output:

\begin{frame}[fragile]{My Slide}
\protect\hypertarget{my-slide}{}

\begin{lstlisting}[escapechar=£,language=haskell]
myFunc = do
  £\CodeEmphasis{one}£ £\CodeEmphasis{two}£ £\CodeEmphasis{thre}£e
  £\CodeEmphasis{four}£ £\CodeEmphasis{five}£ six
  £\CodeEmphasisLine{seven}£ £\CodeEmphasisLine{eight}£ £\CodeEmphasisLine{nine}£
  ten eleven twelve
\end{lstlisting}

\end{frame}

and you can see \CodeEmphasisLine is wrapped around each word in the line, rather than the line itself. This has no consequences the styling is purely on the text (i.e. \textit), but when the styling involves the background color it leads to a PDF with a series of blocks around each word, with white/background-space in between the highlighted words.

pandoc-emphasize-code: user error (Invalid position: 2)

Hello! Good job with the package. I'm a new contributor and I think that the filter gives an error with whole-line ranges when I tried it out of the box.

I set up the pandoc-emphasize-code binary with:

wget -O ~/Downloads/ 'https://github.com/owickstrom/pandoc-emphasize-code/releases/download/v0.2.3/pandoc-emphasize-code-osx-ghc8-pandoc-1-19.tar.gz'
tar -xvzf ~/Downloads/pandoc-emphasize-code-osx-ghc8-pandoc-1-19.tar.gz

I set up a file ~/Downloads/temp.md with the example in the Readme:

```{.haskell emphasize=2-2,3:3-3:12}
myFunc = do
  newStuffHere
  andThisToo notThis
  notSoRelevant
```

Then I run:

$ pandoc --filter ~/Downloads/pandoc-emphasize-code -o ~/Downloads/temp.html ~/Downloads/temp.md
pandoc-emphasize-code: user error (Invalid position: 2)
Error running filter ~/Downloads/pandoc-emphasize-code:
Filter returned error status 1

If I remove the first range and the markdown file looks like:

```{.haskell emphasize=3:3-3:12}
myFunc = do
  newStuffHere
  andThisToo notThis
  notSoRelevant
```

Then pandoc makes the output without problems.

Does not compile with pandoc-types-1.20

Compilation fails with the following error:

[7 of 9] Compiling Text.Pandoc.Filter.EmphasizeCode.Latex
/private/var/folders/3b/9plp3gb959gcv_nyqg9j_k740000gn/T/stack70671/pandoc-emphasize-code-0.2.4/src/Text/Pandoc/Filter/EmphasizeCode/Latex.hs:48:8: error:
    • Couldn't match type ‘[Char]’ with ‘Text’
      Expected type: Text
        Actual type: String
    • In the second argument of ‘Pandoc.RawBlock’, namely
        ‘(Text.unpack (encloseInVerbatim emphasized))’
      In the expression:
        Pandoc.RawBlock
          (Pandoc.Format "latex")
          (Text.unpack (encloseInVerbatim emphasized))
      In an equation for ‘renderEmphasized’:
          renderEmphasized _ (_, classes, _) lines'
            = Pandoc.RawBlock
                (Pandoc.Format "latex")
                (Text.unpack (encloseInVerbatim emphasized))
            where
                languageAttr
                  = case classes of
                      [lang] -> ",language=" <> Text.pack lang
                      _ -> ""
                encloseInTextIt style t
                  | Text.null t = t
                  | otherwise
                  = case style of
                      Inline -> "£\\CodeEmphasis{" <> t <> "}£"
                      Block -> "£\\CodeEmphasisLine{" <> t <> "}£"
                emphasizeNonSpace style t
                  | Text.null t = t
                  | otherwise = let ... in mconcat [...]
                emphasizeChunk chunk
                  = case chunk of
                      Literal t -> t
                      Emphasized style t
                        -> emphasizeNonSpace style (Text.concatMap escaped t)
                ....
   |
48 |       (Text.unpack (encloseInVerbatim emphasized))
   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/private/var/folders/3b/9plp3gb959gcv_nyqg9j_k740000gn/T/stack70671/pandoc-emphasize-code-0.2.4/src/Text/Pandoc/Filter/EmphasizeCode/Latex.hs:52:47: error:
    • Couldn't match type ‘Text’ with ‘[Char]’
      Expected type: String
        Actual type: Text
    • In the first argument of ‘Text.pack’, namely ‘lang’
      In the second argument of ‘(<>)’, namely ‘Text.pack lang’
      In the expression: ",language=" <> Text.pack lang
   |
52 |           [lang] -> ",language=" <> Text.pack lang
   |                                               ^^^^

Allow linewise ranges

First just let me say that I'm a big fan of this filter; thanks!

I'd like to achieve an affect similar to this example in the React docs:

screen shot 2018-06-08 at 12 11 03 am

In particular, I'd like to be able to specify that entire lines should be highlighted, from the far left of the <pre> tag to the far right. With a bit of tinkering, I managed to get this working in the Chrome inspector almost entirely with CSS:

screen shot 2018-06-08 at 12 05 13 am

The one trick is that I had to add a CSS class to the generated <mark> tags to indicate whether it should mark within the line (.inline) or the entire line (.block):

<pre><code>```{.haskell <mark class="inline">emphasize=2:3-2:14,3:3-3:12</mark>}
myFunc = do
<mark class="block">  newStuffHere</mark>
  andThisToo notThis
  notSoRelevant
```</code></pre>

I'm considering patching the pandoc-emphasize-code grammar to accept ranges like this:

line number     = natural number;
column number   = natural number;
position        = line number, ":", column number;
range           = position, "-", position
                | line number, "-", line number;           (* new *)
ranges          = range, { (",", range) };

This would allow enough information to be tracked to determine whether we should put the .inline class or the .block class on the generated tag. It's also slightly friendlier; in case the code changes within a line, you don't need to update the column positions to ensure that all the characters on that line remain highlighted.

Curious to hear your thoughts on whether this would be a welcome change, and whether you have preferences for how it should be implemented.

Thanks again for this filter!


P.S. This was the bit of CSS needed to get it to work:

pre code {
  position: relative;
  min-width: 100%;
  z-index: 1;
}

mark.block::after {
    content: "";
    position: absolute;
    background-color: yellow;
    left: -16px;
    right: -16px;
    height: 19px;
    margin-top: 2px;
    z-index: -1;
}

"Incompatible API versions" with pandoc 2.9.1.1

When trying to use pandoc-emphasize-code with the latest pandoc 2.9.1.1, I get the following error:

pandoc-emphasize-code: Error in $: Incompatible API versions: encoded with [1,20] but attempted to decode with [1,17,3].
CallStack (from HasCallStack):
  error, called at ./Text/Pandoc/JSON.hs:111:48 in pandoc-types-1.17.3-8FqBpKHzarl96XxtefXvVq:Text.Pandoc.JSON
Error running filter ../common/pandoc-emphasize-code:
Filter returned error status 1

Here is my pandoc version:

pandoc --version
pandoc 2.9.1.1
Compiled with pandoc-types 1.20, texmath 0.12, skylighting 0.8.3

I suppose the filter must be rebuilt for pandoc-types 1.20?

Use highlight.js with reveal.js

I realize that I'm several layers down a rabbit hole, but it looks like you have a great tool and that it should be able to match my use case 😄

My flow is as follows:

  • Write my presentation in Markdown
  • Run the command pandoc testing.md -o testing.html -s -i -t revealjs --no-highlight --css reveal.js/lib/css/monokai.css --filter pandoc-emphasize-code

In the README, at the bottom of the Rendering to HTML section, it claims that you should be able to use highlight.js with this tool. However, in my use case, it simply adds the <mark> tags to the formatted code, as if it was part of the original fenced code.

Do you have any tips on how to get this to work? Thanks!

Use blaze or lucid in HTML emphasizer

Currently, the HTML/GitHub Markdown emphasizer is stringly-typed, bashing together Text values. No escaping or such. 😢 Should be rewritten to use Blaze or Lucid.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.