Skip to content
Search
Search the documentation
Code blocks
GitHub GitHub
3 min read

Code blocks

Highlight lines, mark diffs, focus, flag errors, and highlight words.

Every fenced code block is highlighted by Shiki at build time. On top of that, you annotate lines and words with comment markers written right in the code. The marker comment is stripped from the rendered output, so what readers see stays clean.

Each section below shows the markdown you write, then how it renders.

Highlight a line

Append // [!code highlight] to a line (a real comment in the fence’s language) to give it a highlighted background.

You write:

			const config = defineConfig({
	title: 'My Library' // [!code highlight]
});
		

Which renders as:

			const config = defineConfig({
	title: 'My Library'
});
		

Additions and deletions

Mark a line with // [!code ++] for an addition or // [!code --] for a deletion. They render with a colored background and a + / - gutter marker.

You write:

			export default {
	preprocess: [vitePreprocess()],             // [!code --]
	preprocess: [vitePreprocess(), docsmith()], // [!code ++]
};
		

Which renders as:

			export default {
	preprocess: [vitePreprocess()], 
	preprocess: [vitePreprocess(), docsmith()] 
};
		

Focus

// [!code focus] dims the other lines so the eye lands on what matters. Hover the rendered block to bring the rest back.

You write:

			function setup() {
	const app = createApp();
	app.use(docsmith()); // [!code focus]
	return app;
}
		

Which renders as:

			function setup() {
	const app = createApp();
	app.use(docsmith()); 
	return app;
}
		

Errors and warnings

// [!code error] and // [!code warning] tint a line red or amber, for call-outs like a deprecated call or a footgun.

You write:

			const ok = readFile('./page.md');
const bad = readFile();                  // [!code error]
const risky = readFileSync('./page.md'); // [!code warning]
		

Which renders as:

			const ok = readFile('./page.md');
const bad = readFile(); 
const risky = readFileSync('./page.md'); 
		

Highlight a word

// [!code word:name] highlights every occurrence of name on the next line. Add a count like word:name:2 to limit how many.

You write:

			const name = frontmatter.title; // [!code word:name]
		

Which renders as:

			const name = frontmatter.title; 
		

Markers use the fence's language

Write the marker inside a comment your language understands: // for JS/TS/Svelte, # for bash or YAML, <!-- --> for HTML. Shiki strips the comment along with the marker, so it never ships to the reader. (To show a marker literally instead of applying it, as the “You write” blocks above do, put it in a plain text block.)

Highlight lines by number

Comment markers can’t reach every line. Inside a Svelte template region an HTML comment is stripped without highlighting anything, so mark those lines from the fence itself instead. A single line, a list, or a range all work.

			```svelte {4}
<DocsShell
	config={siteConfig}
	content={docs}
	search={() => import('svelte-docsmith/search').then((m) => m.docs)}
>
	{@render children()}
</DocsShell>
```
		

renders as:

			<DocsShell
	config={siteConfig}
	content={docs}
	search={() => import('svelte-docsmith/search').then((m) => m.docs)}
>
	{@render children()}
</DocsShell>
		

Ranges and lists use the same syntax: {2-4}, {1,5}, or both together.

Filenames and line numbers

Add title= to label a block with the file it belongs to, and showLineNumbers to number it. Pair startLine= with numbering when the snippet is lifted out of a longer file, so the numbers match the real source.

			```ts title="vite.config.ts" showLineNumbers
import { docsmith } from 'svelte-docsmith/vite';
export default { plugins: [docsmith()] };
```
		

renders as:

vite.config.ts
			import { docsmith } from 'svelte-docsmith/vite';
export default { plugins: [docsmith()] };
		

Numbering every block by default is a preprocessor option, and a single fence can still opt out with noLineNumbers:

svelte.config.js
			docsmith({ lineNumbers: true });
		

Real types on hover

Add twoslash to a TypeScript or Svelte fence and the block is run through the TypeScript compiler, so hovering a token shows its actual inferred type rather than a hand-written guess.

			```ts twoslash
const version = '0.9.0';
const parts = version.split('.').map(Number);
```
		

renders as (hover parts or version):

			const const version: "0.9.0"version = '0.9.0';
const const parts: number[]parts = const version: "0.9.0"version.String.split(separator: string | RegExp, limit?: number): string[] (+1 overload)
Split a string into substrings using the specified separator and return them as an array.
@paramseparator A string that identifies character or characters to use in separating the string. If omitted, a single-element array containing the entire string is returned.@paramlimit A value used to limit the number of elements returned in the array.
split
('.').Array<string>.map<number>(callbackfn: (value: string, index: number, array: string[]) => number, thisArg?: any): number[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
(var Number: NumberConstructor
An object that represents a number of any kind. All JavaScript numbers are 64-bit floating-point numbers.
Number
);

Twoslash is opt-in twice over: enable it in the preprocessor, then mark the individual fences that want it.

svelte.config.js
			docsmith({ twoslash: true });
		

It needs three optional peer dependencies, pulled in only if you use it:

			npm i -D @shikijs/twoslash twoslash-svelte typescript
		

Because the snippet really is compiled, it has to typecheck: an unresolved import or a type error means there is no type to show. Rather than fail your build over one block, DocSmith falls back to an ordinary highlight and warns which block it was. Use // @errors: 2322 to show an error deliberately, // @noErrors to silence one, and // ---cut--- to hide setup lines from the rendered output while still compiling them.

Was this page helpful?