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

wrapLines breaks some code highlighting; fix included #461

Open
benjie opened this issue Sep 7, 2017 · 5 comments
Open

wrapLines breaks some code highlighting; fix included #461

benjie opened this issue Sep 7, 2017 · 5 comments
Labels

Comments

@benjie
Copy link

benjie commented Sep 7, 2017

Where wrapLines splits the code content on \n and wraps it in <div>s if the highlighter opens a <span> on one line and doesn't close it until the next line the browser will auto-close the span in the first div and the second line won't inherit the styles. This causes code formatting to appear broken - I thought it was an issue with highlight.js so switched out for prism as seen in #444 but it persisted.

function wrapLines (block) {
var lines = block.innerHTML.split(/\r?\n/).map(function (line) {
return '<div class="remark-code-line">' + line + '</div>';
});
// Remove empty last line (due to last \n)
if (lines.length && lines[lines.length - 1].indexOf('><') !== -1) {
lines.pop();
}
block.innerHTML = lines.join('');
}

I've managed to work around the issue by pre-empting this in my highlightBlock override and closing spans out at the end of a line and re-opening them at the beginning of the next line. ES6 code to achieve this is here:

function parseLanguage(lang) {
  return {
    js: 'jsx',
  }[lang] || lang;
}
remark.highlighter.engine.highlightBlock = block => {
  const language = parseLanguage(block.className.split(" ")[0]);
  const prismLang = Prism.languages[language];
  if (prismLang) {
    block.parentNode.className = `${block.parentNode.className} language-${language}`;
    const html = Prism.highlight(block.textContent, prismLang);



    const lines = html.split(`\n`);
    let currentSpan = null;
    for (var i = 0; i < lines.length; i++) {
      let line = lines[i];
      if (currentSpan) {
        line = currentSpan + line;
        currentSpan = null;
      }
      const openTags = [];
      const re = /(<span[^>]*>|<\/span>)/gi;
      let matches;
      while ((matches = re.exec(line)) != null) {
        const tag = matches[1];
        if (tag[1] === '/') {
          openTags.pop();
        } else {
          openTags.push(tag);
        }
      }
      currentSpan = openTags.join('');
      line = line + ('</' + 'span>').repeat(openTags.length);
      lines[i] = line;
    }
    block.innerHTML = lines.join('\n');



  } else {
    console.warn(`Language '${language}' not supported?`)
  }
};

Perhaps you'd consider incorporating the part from const lines = html.split... to lines.join('\n') into the wrapLines function directly?

@benjie
Copy link
Author

benjie commented Sep 7, 2017

(I absolutely love this presentation framework by the way, have been using it for years and extoll the virtues of it everywhere I present ❤️ - I've even got an awesome setup now with Browsersync where when you save your markdown file the browser automatically replaces all the slides instantly and jumps to the first edited slide which has increased my productivity significantly!)

@benjie
Copy link
Author

benjie commented Oct 5, 2017

For those interested in my workflow, check out this script:

https://github.com/GraphQLTraining/lightweight-graphql-react/blob/gh-pages/browsersync

And the corresponding main function in the index.html file:

https://github.com/GraphQLTraining/lightweight-graphql-react/blob/gh-pages/index.html

@bcherny
Copy link

bcherny commented Mar 26, 2018

Thank you so much for sharing your setup @benjie - I am literally 2x more productive with it. @gnab How do you feel about adding this to remark as a default dev experience? It's sort of magical.

@kdorland
Copy link

kdorland commented Aug 12, 2020

Oh, this is great, @benjie! I wish I didn't have to hack remark to make it highlight 'jsx' properly. I would settle for an option to disable "highlight.js" and the remark code blocks altogether so I could simply link in my preferred highlighter (prism.js) for my <pre> <code> tags. Or something like that.

@lefred
Copy link

lefred commented Mar 9, 2022

I'm using your changes to (remark.prism.js) to have the syntax highlight and it works fine. Thank you.
Do you know if it will be possible to have some plugins like line-numbers working too ?
Thank you.

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

No branches or pull requests

5 participants