Code blocks
Code sits on the website's dark editor surface in both themes: #202020 on the light page, #161616 on the dark one, framed by the 1.5px rule with 6px corners. Highlighting is Shiki with the dcupl theme (src/lib/shiki-dcupl-theme.ts), and <docs-code-block> renders exactly the same markup as fenced markdown.
The dcupl theme
One theme for both modes, taken from the website's terminals:
| Token | Color |
|---|---|
Keywords (import, const) |
white, bold |
Strings, numbers, true |
mint #b5edbd |
| Types and classes | yellow #ffe58a |
| Comments | gray #8f8f8f |
| Punctuation and operators | light gray #a9a9a9 |
| Everything else | off-white #f2f2f2 |
import type { ModelDefinition } from '@dcupl/common';
// One theme, both modes
const productModel: ModelDefinition = {
key: 'Product',
properties: [
{ key: 'sku', type: 'string', index: true },
{ key: 'inStock', type: 'boolean' },
],
};Basic code block
Without metadata the block has no header; the mint copy button appears on hover or keyboard focus.
const greeting = 'Hello, World!';
console.log(greeting);With filename
Add a filename attribute for a header strip: the file name in mono semibold on a light strip (#f5f5f5, #1f1f1f in dark mode) above the rule, with the mint copy button on the right.
import { ApplicationConfig } from '@angular/core';
export const appConfig: ApplicationConfig = {
providers: [],
};With title
Use title for a descriptive header instead of a file name:
npm install @dcupl/coreTabbed code groups
Consecutive code blocks with the same group become one panel with tabs. Tabs are mono pills with a hairline outline; the selected tab is filled with ink.
Package manager options
npm install @dcupl/coreyarn add @dcupl/corepnpm add @dcupl/coreFramework examples
import { Component, inject } from '@angular/core';
import { DcuplService } from './dcupl.service';
@Component({
selector: 'app-products',
template: `<ul>
@for (item of items(); track item.key) {
<li>{{ item.name }}</li>
}
</ul>`,
})
export class ProductsComponent {
private dcupl = inject(DcuplService);
items = this.dcupl.query('Product');
}import { useDcupl } from '@dcupl/react';
export function Products() {
const { items } = useDcupl('Product');
return (
<ul>
{items.map(item => (
<li key={item.key}>{item.name}</li>
))}
</ul>
);
}<script setup>
import { useDcupl } from '@dcupl/vue';
const { items } = useDcupl('Product');
</script>
<template>
<ul>
<li v-for="item in items" :key="item.key">
{{ item.name }}
</li>
</ul>
</template>Dollar patterns stay literal
Code renders exactly as written, including the String.prototype.replace patterns ($&, $1, $', $$ and the backtick form). Write samples in their natural form; there is no need to avoid them. scripts/markdown-code-blocks.spec.ts checks every code block path (plain, headers, groups, alerts, tabs, mermaid).
// Escape regex characters in user input
const escapeRegExp = (value: string) => value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
// Swap "Last, First" to "First Last"
const name = 'Doe, Jane'.replace(/(\w+), (\w+)/, '$2 $1');
// Text before and after the match: "key [key|value] value"
const context = 'key=value'.replace('=', " [$`|$'] ");
// A literal dollar sign in a template string
const price = `$${amount.toFixed(2)}`;Under a model: the live preview
On a concept page, a model's code can carry a docs-model-preview underneath: a table of demo items whose columns light up together with the property lines in the code. See Data display and SDK › Models.
Usage
Filename syntax
```typescript filename="example.ts"
// Your code here
```Title syntax
```bash title="Run the server"
npm run dev
```Tabbed group syntax
```bash group="install" tab="npm"
npm install package
```
```bash group="install" tab="yarn"
yarn add package
```Note: Tabbed groups need consecutive code blocks with the same group value. Any content between the blocks breaks the group.