The content-render subject is the main pipeline that converts content from Liquid, Markdown, and YAML into HTML. It handles template processing, Markdown parsing, custom Liquid tags, and unified (remark/rehype) transformations. This directory does not include React components.
This subject is responsible for:
- Rendering Liquid templates with context variables
- Converting Markdown to HTML with unified (remark/rehype)
- Custom Liquid tags for content and data references
- Code block syntax highlighting and headers
- Link rewriting (local paths, assets, anchors)
- Image transformations and wrapping
- Alert/note callout rendering
- Table accessibility improvements
- Text-only extraction for search indexing
index.ts-renderContent(): Main entry point for content renderingliquid/engine.ts- Liquid engine with custom tag registrationunified/processor.ts- Unified pipeline with remark/rehype pluginsliquid/*.ts- Custom Liquid tags (data, ifversion, octicon, etc.)unified/*.ts- Content transformation plugins
import { renderContent } from '@/content-render'
const html = await renderContent(`
# Beep
{{ foo }}
`, {
foo: 'bar'
})Creates:
<h1 id="beep"><a href="#beep">Beep</a></h1>
<p>bar</p>Render a string of markdown with optional context. Returns a Promise.
Liquid will look for includes in ${process.cwd()}/includes.
Options:
fileName: File name for debugging purposestextOnly: Output text instead of HTML using cheerio (for search indexing)
The Liquid instance used internally for direct access.
Add a header to code blocks with the copy annotation:
```js copy
const copyMe = true
```
The un-highlighted text is available as button.js-btn-copy's data-clipboard-text attribute.
- Markdown content with Liquid templates
- Context object with variables and functions
- Data from
data/directory (reusables, variables, features) - Content includes from
includes/directory
- LiquidJS - Template engine for Liquid processing
- unified/remark/rehype - Markdown to HTML transformation
- cheerio - HTML parsing for text-only mode
- highlight.js - Syntax highlighting for code blocks
- Custom plugins for GitHub-specific transformations
- Liquid rendering - Process Liquid tags and variables
- Markdown parsing - Convert to syntax tree (remark)
- Unified plugins - Apply transformations
- HTML generation - Convert to final HTML (rehype)
- Post-processing - Additional cleanup if needed
src/frame- Page rendering uses renderContentsrc/data-directory- Data accessed via {% data %} tagssrc/versions- {% ifversion %} tag logic- All content in
content/- Source of Markdown to render - Includes in
includes/- Reusable Liquid includes
- Liquid helpers guide
- Content style guide - Using Liquid tags in content
- Team: Docs Engineering
Custom tags implemented:
| Tag | Purpose |
|---|---|
{% data variables.product.product_name %} |
Access data variables |
{% ifversion fpt %}...{% endif %} |
Conditional content by version |
{% octicon "check" %} |
Render Octicons |
{% indented_data_reference foo.bar spaces=2 %} |
Data reference with indentation |
{% tool name %} |
Tool-specific content |
{% prompt %} |
Command prompt styling |
See contributing/liquid-helpers.md for complete list.
Tags can be used in:
- Articles and TOCs (
content/**/*.md) - Include files (
includes/*.html)
Tags expect language-agnostic hrefs or data paths:
{% data variables.product.product_name %}
{% ifversion ghes > 3.9 %}...{% endif %}- Create TypeScript class in
liquid/my-tag.tsand implement the rendering logic directly in the class (using inline HTML or template strings). - Register in
liquid/engine.ts:import MyTag from './my-tag' engine.registerTag('my_tag', MyTag)
- Add tests in
tests/ - Document in
contributing/liquid-helpers.md
See LiquidJS docs for tag API.
Plugins transform the Markdown AST:
rewrite-local-links- Rewrites internal/en/...linksrewrite-asset-urls- Handles/assets/...pathsheading-links- Adds anchor links to headingsalerts- Converts> [!NOTE]to styled alertscode-header- Adds copy buttons to code blocks- And many more...
- Create plugin in
unified/my-plugin.ts - Add to processor in
unified/processor.ts - Add tests
- Consider impact on performance (plugins run on every render)
- Liquid rendering happens before Markdown parsing (can't use Markdown in Liquid output easily)
- Some transformations are performance-sensitive (cached where possible)
- Text-only mode used for search has different output than HTML mode
- Custom Liquid tags must be registered manually
- Rendering is cached at the page level
- Liquid includes are resolved on every render
- Heavy transformations should be avoided in hot paths
- Use
textOnlymode for search indexing (faster)