SSR Rendering Test — Complete Element Coverage
This document exercises every block and inline element to compare SSR (subdomain) vs CSR (editor) rendering.
Typography Scale
Heading 1 — The Biggest Title
Heading 2 — Section Header
Heading 3 — Subsection
Heading 4 — Minor Section
Heading 5 — Small Label
Heading 6 — Smallest
Regular paragraph text at 16px base. This is the default prose body with proper line-height (1.7) and letter-spacing (-0.003em). The system font stack should render crisply across all platforms.
Inline Formatting
This paragraph has bold text, italic text, bold italic, strikethrough, inline code, and a hyperlink. Here is highlighted text and green highlight and blue highlight and red highlight.
Mixing inline styles: bold with inline code inside and italic with a link inside.
Block Quotes
Simple blockquote — a single line of quoted text with left border accent.
Multi-line blockquote that spans several sentences to test wrapping behavior. The left border should extend the full height. Text color should be muted compared to body text.
Second paragraph inside the same blockquote to verify paragraph spacing within quotes.
Callout Boxes
This is a note callout. Used for supplementary information that adds context without being critical.
This is a tip callout. Suggests best practices or shortcuts the reader might find useful.
This is a warning callout. Alerts the reader to potential pitfalls or important caveats.
This is a caution callout. Indicates danger or a high-risk action that could cause problems.
This is an important callout. Highlights crucial information the reader should not skip.
Lists
Unordered List
First item in the list
Second item with bold and
codeNested item level 2
Another nested item
Level 3 nesting
Back to top level
Ordered List
First numbered item
Second numbered item
Nested numbered 2.1
Nested numbered 2.2
Third item with a longer description that wraps to multiple lines to test alignment of subsequent lines with the number indent
Task List
Unchecked task item
Completed task item
Another pending task with bold text
Done — verify checkbox alignment with text
Tables
Simple Table
Feature | Status | Notes |
|---|---|---|
Syntax Highlighting | Active | Shiki via CDN |
Mermaid Diagrams | Active | Full zoom/pan/fullscreen |
Math Rendering | Active | KaTeX via CDN |
Dark Mode | Active | MutationObserver on .dark |
Copy Button | Active | Clipboard API |
Wide Table (Overflow Test)
Component | File Path | Size | Dependencies | Build Time | CDN Loaded | SSR Compatible | Dark Mode |
|---|---|---|---|---|---|---|---|
CodeBlockView | packages/block-editor/src/ui/CodeBlock/CodeBlockView.component.tsx | 200 lines | lucide-react, LanguagePicker | 0.5s | No | Yes | Yes |
CodeBlockIsland | packages/block-editor/src/ui/CodeBlock/CodeBlockIsland.component.tsx | 280 lines | dynamicImport, MermaidPreview, MathPreview | 0.3s | shiki, mermaid, katex | Yes | Yes |
MermaidRenderer | packages/block-editor/src/ui/CodeBlock/renderers/MermaidRenderer.component.tsx | 355 lines | mermaid, lucide-react | 0.8s | No | No | Yes |
Code Blocks
JavaScript
async function mountCodeBlockIslands() {
const blocks = document.querySelectorAll('pre.block-code-block');
if (blocks.length === 0) return;
const theme = detectTheme();
blocks.forEach((pre) => {
const codeEl = pre.querySelector('code');
if (!codeEl) return;
const code = codeEl.textContent || '';
const language = codeEl.getAttribute('data-language') || 'plaintext';
const wrapper = document.createElement('div');
wrapper.className = 'code-block-nodeview';
pre.replaceWith(wrapper);
createRoot(wrapper).render(
createElement(CodeBlockIsland, { code, language, theme })
);
});
}TypeScript
interface CodeBlockViewProps {
language: string;
theme: 'light' | 'dark';
readOnly: boolean;
viewMode: ViewMode;
showLineNumbers: boolean;
wordWrap: boolean;
copied: boolean;
highlightHtml: string;
diffHtml: string;
onViewModeChange?: (mode: ViewMode) => void;
onLanguageChange?: (lang: string) => void;
onCopy?: () => void;
contentSlot: ReactNode;
previewSlot?: ReactNode;
lineCount: number;
}
type ViewMode = 'code' | 'preview' | 'split';Python
class MermaidRenderer:
"""Renders mermaid diagrams with dark mode support."""
ZOOM_STEP = 0.25
MIN_ZOOM = 0.25
MAX_ZOOM = 5.0
def __init__(self, theme: str = "light"):
self.theme = theme
self.config = self._get_config()
def _get_config(self) -> dict:
return {
"startOnLoad": False,
"securityLevel": "strict",
"theme": "dark" if self.theme == "dark" else "base",
"fontFamily": "-apple-system, BlinkMacSystemFont, sans-serif",
}
async def render(self, code: str) -> str:
svg = await self._mermaid_render(code)
if self.theme == "dark":
svg = self._adapt_colors_for_dark(svg)
return svgCSS
.code-block-wrapper {
position: relative;
border: 1px solid var(--be-border, #e5e7eb);
border-radius: 0.5rem;
overflow: hidden;
background: var(--be-code-bg, #f8f9fa);
font-family: "JetBrains Mono", "Fira Code", "Cascadia Code",
"Menlo", "Monaco", "Consolas", monospace;
font-size: 0.875rem;
line-height: 1.5;
transition: border-color 0.15s ease;
}
.code-block-wrapper--dark {
background: var(--be-code-bg-dark, #1e1e2e);
border-color: var(--be-border-dark, #313244);
}
.dark .block-table th {
background: var(--table-header-bg, #2d3748);
color: var(--table-header-text, #e2e8f0);
}Bash
#!/bin/bash
# Deploy subdomain worker to Cloudflare
cd apps/subdomain
yarn build
echo "Bundle size: $(du -sh dist/server/ | cut -f1)"
echo "Chunk count: $(ls dist/server/chunks/ | wc -l)"
CLOUDFLARE_API_TOKEN="$CLB_CLOUDFLARE_API_TOKEN" yarn deploy
echo "Deployed successfully!"JSON
{
"name": "@colbin/block-editor",
"version": "0.1.0",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js",
"require": "./dist/index.cjs"
},
"./islands/codeblock": "./src/ui/CodeBlock/mountCodeBlockIslands.ts",
"./styles.css": "./dist/block-editor.css"
},
"peerDependencies": {
"shiki": "^3.0.0",
"mermaid": "^11.0.0",
"katex": "^0.16.0",
"react": "^19.0.0"
}
}Diff
- import { MermaidRenderer } from './renderers/MermaidRenderer.component';
- import { MathRenderer } from './renderers/MathRenderer.component';
+ // Renderers moved to previewSlot — injected by consumers
+ // Editor passes bundled renderers, SSR island passes CDN-loaded ones
export const CodeBlockView = React.memo(({
- code,
language,
theme,
readOnly,
+ previewSlot,
contentSlot,
}) => {Mermaid Diagrams
Flowchart
flowchart TD
SSR[SSR HTML Response] --> Hydrate[React Island Hydration]
Hydrate --> Detect{Detect Theme}
Detect -->|Light| Light[Light Config]
Detect -->|Dark| Dark[Dark Config]
Light --> Mount[Mount CodeBlockIslands]
Dark --> Mount
Mount --> Shiki[Shiki CDN Highlight]
Mount --> Mermaid[Mermaid CDN Render]
Mount --> KaTeX[KaTeX CDN Render]
Shiki --> Display[Display Enhanced Blocks]
Mermaid --> Display
KaTeX --> Display
style SSR fill:#4a9eff,color:#fff
style Display fill:#10b981,color:#fff
style Detect fill:#f59e0b,color:#fffSequence Diagram
sequenceDiagram
participant B as Browser
participant W as CF Worker
participant A as API Server
participant C as CDN (esm.sh)
B->>W: GET org.colbin.com/bin/slug
W->>A: Fetch pre-rendered HTML
A-->>W: HTML + metadata
W-->>B: Full SSR page
Note over B: React island hydrates (client:idle)
B->>C: import('shiki')
C-->>B: Shiki bundle
B->>C: import('mermaid')
C-->>B: Mermaid bundle
Note over B: Code blocks enhanced with<br/>syntax highlighting + diagrams
B->>B: User toggles dark mode
Note over B: MutationObserver fires<br/>Re-render all islandsMath / LaTeX
E = mc^2\int_{-\infty}^{\infty} e^{-x^2} dx = \sqrt{\pi}\frac{\partial f}{\partial x} = \lim_{h \to 0} \frac{f(x+h) - f(x)}{h}Horizontal Rules
Content above the rule.
Content below the rule. Rules should have consistent vertical spacing.
Mixed Content Stress Test
Here is a paragraph with bold, italic, inline code, and a link. It references the CodeBlockView component which accepts a previewSlot?: ReactNode prop.
The dynamicImport() function uses new Function() to bypass Vite's static analysis. This is guarded with typeof window === 'undefined' for Cloudflare Workers compatibility.
Below is a table followed immediately by a code block:
Approach | Bundle Size | CDN Load |
|---|---|---|
Bundled | 19 MiB | None |
CDN | 1.7 MiB | ~2 MiB async |
// The dynamicImport trick that saved 17MB
function dynamicImport(specifier: string): Promise<any> {
if (typeof window === 'undefined') {
return Promise.reject(new Error('client-only'));
}
return new Function('s', 'return import(s)')(specifier);
}And a mermaid diagram right after:
graph LR
A[19 MiB Bundle] -->|CDN externalize| B[1.7 MiB Bundle]
B -->|+ esm.sh| C[Full Features]
style A fill:#ef4444,color:#fff
style B fill:#10b981,color:#fff
style C fill:#3b82f6,color:#fffEnd of rendering test document. Compare this page between SSR (subdomain) and CSR (editor) for visual parity.