#Code Highlighting on server side

12 messages · Page 1 of 1 (latest)

celest marlin
#

I am writing a blog which currently compiles directly to HTML and CSS, without any JS which is nice. I need to add a code block to my blog and I would like it to have syntax highlighting without needing any JS sent to the client side. How can this be done?

upper dewBOT
#

Hi @celest marlin. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:

#

Astro provides built-in support for syntax highlighting for code blocks at build time, which means no client-side JavaScript is included. This is achieved using the <Code /> component, which is powered internally by Shiki. Shiki supports all popular themes and languages, and you can add your custom themes, languages, and transformers by passing them to the theme, lang, and transformers attributes respectively.

Here's an example of how to use the <Code /> component:

import { Code } from 'astro:components';

<Code code={`const foo = 'bar';`} lang="js" />

You can also customize the theme and enable word wrapping:

<Code code={`const foo = 'bar';`} lang="js" theme="dark-plus" wrap />

If you want to apply transformers, you can pass them in through the transformers property as an array:

import { transformerNotationFocus } from '@shikijs/transformers';
import { Code } from 'astro:components';

const code = `const foo = 'hello';
const bar = ' world';
console.log(foo + bar) // [!code focus]`;

<Code code={code} lang="js" transformers={[transformerNotationFocus()]} />

Remember that transformers only applies classes and you must provide your own CSS rules to target the elements of your code block.

For more information, you can refer to the Astro documentation (https://docs.astro.build/en/reference/api-reference/#code-).

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@celest marlin kapa.ai is still learning and improving, please let us know how it did by reacting below

celest marlin
#

@upper dew how do i style every code block?

upper dewBOT
#

Let me check the knowledge base for you. One moment! :books:

#

Astro provides several ways to style code blocks.

  1. Using Shiki with Astro's <Code /> component: You can customize the theme used for syntax highlighting. Shiki, the default syntax highlighter used by Astro, allows you to choose from its built-in themes or add your own. Here's an example of how to set the theme:
<Code code={`const foo = 'bar';`} lang="js" theme="dark-plus" />

You can also provide multiple themes and enable word wrapping:

export default defineConfig({
  markdown: {
    shikiConfig: {
      themes: {
        light: 'github-light',
        dark: 'github-dark',
      },
      wrap: true,
    },
  },
});
  1. Using Expressive Code with Starlight: Starlight uses Expressive Code to render code blocks. You can use any of the standard Expressive Code configuration options as well as some Starlight-specific properties, by setting them in Starlight’s expressiveCode option. For example, you can override the default CSS to give your code blocks rounded corners:
starlight({
  expressiveCode: {
    styleOverrides: { borderRadius: '0.5rem' },
  },
});
  1. Using Prism with Astro's <Prism /> component: If you're using the Prism highlighter component, you need to provide a Prism CSS stylesheet for syntax highlighting to appear. You can learn more about configuring Prism stylesheets in the Prism configuration section (https://docs.astro.build/en/guides/markdown-content/#prism-configuration) of the Astro documentation.

Remember to replace the .shiki class in the examples with .astro-code when following Shiki’s documentation to customize light/dark dual or multiple themes.

#

@celest marlin kapa.ai is still learning and improving, please let us know how it did by reacting below

celest marlin
#

@upper dew

---
interface Props {
    number: string;
    correct: string;
}

const { number, correct } = Astro.props;

const options = ["A", "B", "C", "D", "E"];

---

<h3 id={number}>{number}</h3>

<slot />


<ul>
    {options.map(option => {
        return (<li>
        <label><input type="radio" autocomplete="off" name={"Q"+number} id={"Q"+number+"A"} /><span> <slot name={option}/></span></label>
    </li>);
    })}
</ul>

<br /><hr /><br />

        <Question number="1" correct="1">
            <p>Consider the following code segment.</p>
            <Code
                code={`public static String calculate() {
    try {
        throw new RuntimeException();
    } catch (RuntimeException e) {
        return "Cats are the best!";
    } finally {
        return "Dogs are the best!";
    }
}`}
                lang="java"
                wrap
            />
            <p>
                What is the result of calling the <b>calculate</b> function?
            </p>

            <h slot="A">The method generates a <b>RuntimeException</b>.</h>
            <h slot="B">Compilation fails due to "unreachable statement".</h>
            <h slot="C">"Cats are the best!"</h>
            <h slot="D">"Dogs are the best!"</h>
            <h slot="E">None of the above.</h>
        </Question>

error: slot[name] must be a static string

upper dewBOT
#

Let me check the knowledge base for you. One moment! :books:

#

The error you're encountering is due to the dynamic generation of slot names in your Astro component. According to the Astro documentation (https://docs.astro.build/en/basics/astro-components/#named-slots), it's not possible to dynamically generate an Astro slot name, such as within a map function.

In your case, you're trying to dynamically generate slot names with this line of code:

<span> <slot name={option}/></span>

Here, option is a variable, and its value changes with each iteration of the map function. This is not allowed in Astro.

If you need to generate dynamic slots, it might be best to generate these within a UI framework component itself, rather than in Astro. If you're using a UI framework component, you can pass static content generated by Astro components as children to your framework components inside an .astro component. You can find more information about this in the Astro documentation (https://docs.astro.build/en/guides/framework-components/#can-i-use-astro-components-inside-my-framework-components).

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: