vitepress icon indicating copy to clipboard operation
vitepress copied to clipboard

Support code groups and allow adding title to code blocks

Open jd-solanki opened this issue 3 years ago • 16 comments
trafficstars

Is your feature request related to a problem? Please describe.

VueJS community is moving from JS to TS now. Hence, we have to provide both TS & JS code.

I already started using VitePress alpha in my OSS project but for another project, I prefer providing TS & JS code via code groups like VuePress.

Describe the solution you'd like

Provide code blocks via markdown (using component is bit ugly for markdown only content). We can inspire from Nuxt content 2 for new syntax

:::code group

:::group{ts}

```ts
const a: number = 1
```

:::

:::group{js}

```js
const a = 1
```

:::

:::

Describe alternatives you've considered

None

Additional context

https://content.nuxtjs.org/guide/writing/mdc

Validations

jd-solanki avatar Jun 06 '22 06:06 jd-solanki

Maybe it could be simpler?

:::code group
```ts
const a: number = 1
```

```js
const a = 1
```
:::

kecrily avatar Jun 06 '22 06:06 kecrily

@kecrily I guess the OP meant to have title of each group too. :::group{foo} --> title is foo.

brc-dd avatar Jun 06 '22 06:06 brc-dd

We can custom group title in code block

```ts [TypeScript]
const a: number = 1
```

Minimizing layers (especially this kind without indentation) is useful to keep the plain text readability of markdown.

kecrily avatar Jun 06 '22 06:06 kecrily

Looking forward this feature, which will have a different experience with such code experience: image

Zhengqbbb avatar Jun 07 '22 16:06 Zhengqbbb

Can we expose the markdown-it rendered to be used inside of Tab components? It would be really nice to be able to use Vue components to render tab groups:

<Tabs>
  <Tab name="TypeScript">
    ``ts
    nested fenced code block here.
    ``
  </Tab>
  <Tab name="JavaScript">
  ``js
    nested fenced code block here.
  ``
  </Tab>
</Tabs>

The goal would be to use the same renderer in a clean way in order to more-easily reuse the same markdown styles.

marshallswain avatar Jun 09 '22 00:06 marshallswain

@marshallswain Sorry, I didn't get you. You can still do what you've wrote. You need to add spaces before and after the fences in this. HTML (or Vue in this case) should be separated from Markdown by empty lines.

brc-dd avatar Jun 09 '22 03:06 brc-dd

@brc-dd wow! I can't believe it was that simple. I just needed the extra line breaks and it now works as expected. Thank you!

marshallswain avatar Jun 10 '22 00:06 marshallswain

Off-topic: this behavior is consistent with that on GitHub. On GitHub you can also embed markdown in html with line breaks.

kecrily avatar Jun 10 '22 04:06 kecrily

@kecrily This is part of the CommonMark standard actually (https://spec.commonmark.org/0.29/#html-blocks). Anything that follows or is based on that will properly render that.

brc-dd avatar Jun 10 '22 06:06 brc-dd

I am also building js + ts docs. Code groups will be a great addition to show ts and js code.

alokVishu avatar Jun 20 '22 11:06 alokVishu

I prefer nuxt's solution like the following

UI: https://v3.nuxtjs.org/guide/directory-structure/layouts#overriding-a-layout-on-a-per-page-basis 图片

Grammar: https://github.com/nuxt/framework/blob/d135608ef0d607259c0ae6f5156c8f46ff78ddc3/docs/content/2.guide/3.directory-structure/7.layouts.md?plain=1#L140-L175

Sepush avatar Jul 22 '22 07:07 Sepush

Also track #1027 here. I think we should go with what @kecrily wrote. Its similar to what we have in Nuxt too.

brc-dd avatar Jul 22 '22 08:07 brc-dd

Hi, I'm interested in taking this, and have some questions on the implementation. Currently code block's function (line number, highlight, etc.) is based on plugin with mdit and pure DOM operation, which is perfect for the static component. But code group (such as in nuxt doc) is a dynamic component, which seems better to have a SFC for it. What do you think? @brc-dd

My current thought is to use a simple component wrap over the doc blocks by slot. And use pure dom operation to control the tab change inside. Any suggestion is welcomed since I'm a newbie to vue. Thanks!

Nuxt reference: https://github.com/nuxt/content/blob/v1/packages/theme-docs/src/components/global/base/CodeGroup.vue

VoVAllen avatar Aug 24 '22 11:08 VoVAllen

@VoVAllen I don't think highlighting and all needs to be done in the code group component. I was thinking of just having a wrapper component (with some md sugar) that can take multiple code blocks (with titles). Regarding tab change, it can be done using basic refs, there is no need to directly manipulate DOM.

brc-dd avatar Aug 24 '22 12:08 brc-dd

@brc-dd Yeah actually this what I thought. I don't want to change the way of highlighting by mdit plugin. My question is whether we need a component(SFC) here or there's a simpler way than SFC.

Current code blocks are <code></code>. My thought for code group is like

<CodeGroup> // This logic is handles by a new SFC

// This is still handled by mdit
<code>
<code/>

<code>
<code/>

</CodeGroup>

which is similar to the container logic but the outside wrapper is a SFC.

What do you think?

VoVAllen avatar Aug 24 '22 12:08 VoVAllen

@VoVAllen Yeah, that's similar to what others wrote. This is the intended syntax BTW:

:::code-group

```js [JavaScript]
some js stuff
```

```ts [TypeScript]
some ts stuff
```

:::

So, if you implement such a component (the one you wrote), then we just need to add some stuff in our markdown component plugin to make it understand :::code-group and ```ts [TypeScript].

brc-dd avatar Aug 24 '22 12:08 brc-dd

Can you guys review #1560 and see if there are any issues (especially with UI)? Here is the deploy preview: https://deploy-preview-1560--vitepress-docs.netlify.app/test

brc-dd avatar Oct 30 '22 18:10 brc-dd

Hi @brc-dd

I am really glad that this is implemented.

UI looks a bit different than what VitePress already provides due to the following:

  • white border Screenshot 2022-10-31 at 11 35 54 AM

  • Removing the hover effect that changes the background color will make it more consistent & minimal like VuePress Screenshot 2022-10-31 at 11 37 41 AM

  • If we will have only two tabs it will look a bit weird (header is not taking full width) Screenshot 2022-10-31 at 11 40 34 AM

In my opinion, VuePress already has an excellent UI, why not reuse it? 🤔

P.S. Sorry I commented here, I should have commented in PR

jd-solanki avatar Oct 31 '22 06:10 jd-solanki