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

Custom highlight function doesn't respect whitespace in code blocks #212

Open
Tracked by #588
michaeloliverx opened this issue Mar 22, 2021 · 5 comments
Open
Tracked by #588
Labels
assigned Whether or not this bug has been assigned some to some other issues as a subtask or pre-req 🕵️ I'm looking into it
Milestone

Comments

@michaeloliverx
Copy link

michaeloliverx commented Mar 22, 2021

HTML Example

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>Example HTML5 Document</title>
  </head>
  <body>
    <p>Test</p>
  </body>
</html>
```

image

Python Example

```python
from typing import Optional

from fastapi import FastAPI
from pydantic import BaseModel


class Item(BaseModel):
    name: str
    description: Optional[str] = None
    price: float
    tax: Optional[float] = None


app = FastAPI()


@app.put("/items/{item_id}")

async def create_item(item_id: int, item: Item, q: Optional[str] = None):

    result = {"item_id": item_id, **item.dict()}
    if q:
        result.update({"q": q})
    return result
```

image

---

UPDATE

As a workaround I got shiki working with the following snippet:

const shiki = require("shiki");

const escape_svelty = (str) =>
  str
    .replace(
      /[{}`]/g,
      (c) => ({ "{": "&#123;", "}": "&#125;", "`": "&#96;" }[c])
    )
    .replace(/\\([trn])/g, "&#92;$1");

async function highlighter(code, lang) {
  const highlighter = await shiki.getHighlighter({ theme: "github-dark" });
  const highlightedCode = escape_svelty(
    highlighter.codeToHtml(code, lang || "text")
  );
  console.log(highlightedCode);
  return `{@html \`${highlightedCode}\` }`;
}

module.exports = {
  extensions: [".svx", ".md"],
  highlight: {
    highlighter: highlighter,
  },
};

It gives me what I want:
image


I don't know the stance MDsveX should take on code blocks.. having flexibility is king and I love being able to customise code output but I think there needs to be more information in the docs about this.

@pngwn
Copy link
Owner

pngwn commented Mar 23, 2021

I wonder why this is happening. Will look into it.

@jthegedus
Copy link

jthegedus commented Oct 7, 2021

@michaeloliverx thanks for sharing your code snippet, it gave me a nice starting point. Sharing my config here as I am consuming the escapeSvelte function from the mdsvex library itself simplifying things a bit:

// mdsvex.config.js
import shiki from "shiki";
import { escapeSvelte } from "mdsvex";

const config = {
  "extensions": [".svelte.md", ".md", ".svx"],

  highlight: {
    highlighter: async (code, lang = "text") => {
      const highlighter = await shiki.getHighlighter({ theme: "github-dark" });
      const highlightedCode = escapeSvelte(highlighter.codeToHtml(code, lang));
      return `{@html \`${highlightedCode}\` }`;
    },
  },

  "smartypants": {
    "dashes": "oldschool",
  },

  "remarkPlugins": [],
  "rehypePlugins": [],
};

export default config;

@michaeloliverx
Copy link
Author

@jthegedus I am glad it helped! Since then I have been using shiki-twoslash its really nice!

Take the following markdown:

```ts twoslash
type Post = {
  title: string;
  description: string;
};


function getPosts(): Array<Post>{
  return []
}

const posts = getPosts();
```

Generates code samples with typescript hints on mouse hover:

image

You can also highlight lines with the following syntax:

```ts twoslash
```ts twoslash {1-4}
type Post = {
  title: string;
  description: string;
};


function getPosts(): Array<Post>{
  return []
}

const posts = getPosts();
```
```

image

It works on non JS/TS code samples too just omit the twoslash directive. You can even add custom properties for example a title or filename:

```ts {1-4} filename="some-file.ts"
type Post = {
  title: string;
  description: string;
};
...
```

They will be added to the pre HTML element as attributes where you could choose to display them using CSS:

image

Anyway enough shilling here is my config file:

// mdsvex.config.js

/**
 * Full MDsveX Options Documentation:
 * https://mdsvex.com/docs#options
 */

import { lex, parse } from "fenceparser";
import { renderCodeToHTML, runTwoSlash, createShikiHighlighter } from "shiki-twoslash";

/** @type {Parameters<typeof import("mdsvex").mdsvex>[0]} */
export const config = {
  extensions: [".svx"],
  highlight: {
    async highlighter(code, lang, meta) {
      // Adapted from the `remark-shiki-twoslash` repo
      // See: https://github.com/shikijs/twoslash/blob/fbf061261fcda90c46e946ce1e2e9357d465c145/packages/remark-shiki-twoslash/src/index.ts#L172-L215
      let fence;

      try {
        fence = parse(lex([lang, meta].filter(Boolean).join(" ")));
      } catch (error) {
        throw new Error(`Could not parse the codefence for this code sample \n${code}`);
      }

      let twoslash;
      if (fence.twoslash === true) {
        twoslash = runTwoSlash(code, lang);
      }

      const highlighter = await createShikiHighlighter({ theme: "github-dark" });
      const html = renderCodeToHTML(code, lang, fence, {}, highlighter, twoslash);
      return `{@html \`${html}\` }`;
    },
  },
};

You will also need some additional CSS, you can find a base under point 3 here: https://github.com/shikijs/twoslash/tree/main/packages/remark-shiki-twoslash#plugin-setup

@jthegedus
Copy link

@michaeloliverx Thanks for pointing me to twoslash, very cool project 🙏

@pngwn pngwn added this to mdsvex Oct 16, 2021
@pngwn pngwn moved this to Refine in mdsvex Oct 16, 2021
@pngwn pngwn added this to the 1.0 milestone Oct 16, 2021
@pngwn pngwn mentioned this issue Feb 23, 2024
13 tasks
@pngwn pngwn added the assigned Whether or not this bug has been assigned some to some other issues as a subtask or pre-req label Feb 24, 2024
@benmccann
Copy link
Contributor

I can't reproduce this. Is it still an issue?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
assigned Whether or not this bug has been assigned some to some other issues as a subtask or pre-req 🕵️ I'm looking into it
Projects
No open projects
Status: Refine
Development

No branches or pull requests

4 participants