Ultra Code Fence

pending

by Rachel Ambler

Advanced code embedding with multiple title styles, icons, line numbers, folding, scrolling, and command output formatting.

9 starsUpdated 1mo agoMITDiscovered via Obsidian Unofficial Plugins
View on GitHub

Ultra Code Fence

CI Coverage License: MIT Obsidian

Ultra Code Fence

Ultra Code Fence extends Obsidian's standard fenced code blocks with advanced embedding, formatting, and display capabilities.

Loosely based on embed-code-file by Abdullah Almariah.

Features

  • Flexible code sources - Embed code directly in your markdown or reference files from anywhere in your vault
  • Space management - Fold lengthy code blocks or enable scrolling to keep your notes tidy
  • Line numbers and zebra striping - Add a numbered gutter and alternating line backgrounds for improved readability
  • Multiple title styles - Display file metadata with customisable title bars in various visual styles
  • Rich descriptions - Annotate code blocks with descriptions that support full markdown formatting, including links to other vault pages
  • Terminal output formatting - Style command output with distinct colours and formatting for prompts, commands, and output text
  • Advanced filtering - Extract specific line ranges or content between markers, with optional chaining

Installation

Manual Installation

  1. Download the latest release
  2. Extract the ultra-code-fence folder to your vault's .obsidian/plugins/ directory
  3. Reload Obsidian
  4. Enable the plugin in Settings > Community plugins

From Community Plugins

Search for "Ultra Code Fence" in Settings > Community plugins > Browse.

Quick Start

Embed a file from your vault:

```ufence-python
META:
  PATH: "vault://scripts/example.py"
```

Embed code directly (inline):

```ufence-bash
META:
  TITLE: "Hello World"
~~~
#!/bin/bash
echo "Hello, World!"
```

Use as a drop-in replacement for standard code fences (no YAML needed):

```ufence-bash
#!/bin/bash
echo "Hello, World!"
```

This renders identically to a standard code fence but with Ultra Code Fence features (copy button, line numbers, zebra striping, etc.) applied from your global settings. No title tab is shown unless you explicitly provide one.

Block Types

Language-specific blocks

Use ufence-{lang} where {lang} is any language in your configured list:

  • ufence-python
  • ufence-bash
  • ufence-javascript
  • ufence-typescript
  • ufence-sql
  • ufence-java
  • ufence-cpp
  • ufence-go
  • ufence-ruby
  • etc.

Generic code block

Use ufence-code with the RENDER.LANG property to specify the language:

```ufence-code
META:
  PATH: "vault://code/example.rs"
RENDER:
  LANG: "rust"
```

Command output block

Use ufence-cmdout to display styled terminal output:

```ufence-cmdout
PROMPT: "^(\\$ )(.*)"
RENDER:
  PROMPT:
    COLOUR: "#6b7280"
~~~
$ ls -la
total 24
drwxr-xr-x  5 user  staff   160 Jan 24 10:00 .
-rw-r--r--  1 user  staff  1234 Jan 24 10:00 file.txt
```

YAML Configuration Structure

Ultra Code Fence uses a nested YAML structure organised into sections:

META:
  PATH: "vault://path/to/file"       # Source file
  TITLE: "{filename} - {size:kb}"    # Title with template variables
  DESC: "Description text"           # Description below title

RENDER:
  FOLD: 0           # 0 = disabled, 1+ = fold to N lines
  SCROLL: 0         # 0 = disabled, 1+ = scroll after N lines
  ZEBRA: false      # Alternating line backgrounds
  LINES: false      # Show line numbers
  COPY: true        # Show copy button
  STYLE: "tab"      # Title bar style
  LANG: "python"    # Language (for ufence-code only)

FILTER:
  BY_LINES:
    RANGE: 10, 50         # Extract lines 10-50
    INCLUSIVE: true       # Include boundary lines (default: true)
  BY_MARKS:
    START: "# BEGIN"      # Start marker
    END: "# END"          # End marker
    INCLUSIVE: true       # Include marker lines (default: true)

For ufence-cmdout blocks:

PROMPT: "^(\\$ )(.*)"     # Top-level regex pattern

RENDER:                   # Styling for cmdout
  PROMPT:
    COLOUR: "#6b7280"
    BOLD: false
    ITALIC: false
  COMMAND:
    COLOUR: "#98c379"
    BOLD: true
    ITALIC: false
  OUTPUT:
    COLOUR: "#abb2bf"
    BOLD: false
    ITALIC: false

META Section

PropertyTypeDescription
PATHstringFile path. Use vault://path/to/file for vault files or https://... for remote URLs
TITLEstringTitle text. If omitted, no title tab is displayed. Supports template variables
DESCstringDescription text shown below or as tooltip

RENDER Section

PropertyTypeDefaultDescription
FOLDnumber00 = disabled, 1+ = fold to N visible lines. Takes precedence over SCROLL
SCROLLnumber00 = disabled, 1+ = scroll after N lines. Ignored if FOLD is active
ZEBRAbooleanfalseAlternate line background colours
LINESbooleanfalseShow line number gutter
COPYbooleantrueShow copy button
STYLEstringtabTitle bar style: tab, integrated, minimal, infobar, none
LANGstring(auto)Language for syntax highlighting (ufence-code only)
SHIFT_COPY_JOINstring(from settings)Join operator used when Shift+clicking the copy button
ALT_COPY_JOINstring(from settings)Join operator used when Alt/Cmd+clicking the copy button. CMD_COPY_JOIN is also accepted
JOIN_IGNORE_REGEXstring(from settings)Regex pattern matching lines to strip before joining (e.g., ^\s*# for shell comments)

FILTER Section

The FILTER section allows extracting specific portions of source code. Filters are applied in order: BY_LINES first, then BY_MARKS on the result.

BY_LINES

PropertyTypeDefaultDescription
RANGEstring-Line range as "start, end" (e.g., "10, 50")
INCLUSIVEbooleantrueInclude boundary lines in output

BY_MARKS

PropertyTypeDefaultDescription
STARTstring-Start marker string to search for
ENDstring-End marker string to search for
INCLUSIVEbooleantrueInclude marker lines in output

Filter Chaining Example

FILTER:
  BY_LINES:
    RANGE: 10, 100      # First: extract lines 10-100
  BY_MARKS:
    START: "# CONFIG"   # Then: find markers within those lines
    END: "# END CONFIG"
    INCLUSIVE: false    # Exclude the marker lines

Copy with Line Joining

The copy button supports modifier keys for joining lines into a single command, useful when a code block contains sequential terminal commands:

  • Click — copies the code as-is
  • Shift+click — joins non-empty lines with the Shift join operator
  • Alt/Cmd+click — joins non-empty lines with the Alt/Cmd join operator

For example, with Shift join set to &&, a block containing:

apt update
apt upgrade
apt autoremove

Shift+click copies as: apt update && apt upgrade && apt autoremove

Join operators are configured in Settings (Code tab) per-language. They can also be overridden per-block:

RENDER:
  SHIFT_COPY_JOIN: "&&"
  ALT_COPY_JOIN: ";"

Ignoring Lines During Join

Use JOIN_IGNORE_REGEX to strip lines matching a regex before joining. This is useful for removing comments from the joined output:

RENDER:
  SHIFT_COPY_JOIN: "&&"
  JOIN_IGNORE_REGEX: "^\\s*#"

With the above configuration, a block containing:

# Update packages
apt update
# Upgrade everything
apt upgrade

Shift+click copies as: apt update && apt upgrade

The ignore regex can also be set per-language in Settings (Code tab). Per-block YAML overrides the per-language default.

PROMPT and RENDER Sections (ufence-cmdout only)

For command output blocks, the PROMPT property is defined at the top level, and styling is controlled via the nested RENDER section.

PROMPT (top-level)

PropertyTypeDescription
PROMPTstringRegex with two capture groups: (prompt)(command)

RENDER Section

The RENDER section contains three subsections for styling different parts of command output:

SubsectionDescription
PROMPTStyling for the prompt text (e.g., $ or >>>)
COMMANDStyling for the command text that follows the prompt
OUTPUTStyling for output lines (lines not matching the prompt pattern)

Each subsection supports these properties:

PropertyTypeDefaultDescription
COLOURstring(from settings)Text colour (CSS colour value)
BOLDbooleanfalseBold formatting
ITALICbooleanfalseItalic formatting

Example Structure

PROMPT: "^(\\$ )(.*)"
RENDER:
  PROMPT:
    COLOUR: "#6b7280"
    BOLD: false
    ITALIC: false
  COMMAND:
    COLOUR: "#98c379"
    BOLD: true
    ITALIC: false
  OUTPUT:
    COLOUR: "#abb2bf"
    BOLD: false
    ITALIC: false

Title Template Variables

Use these variables in META.TITLE or the default title template setting:

File Information

VariableExample OutputDescription
{filename}script.pyFull filename with extension
{basename}scriptFilename without extension
{extension}pyFile extension only
{folder}scriptsParent folder name
{path}scripts/script.pyFull path

File Size

VariableExample OutputDescription
{size}1.5 KBAuto-formatted size
{size:auto}1.5 KBSame as {size}
{size:bytes}1536Size in bytes
{size:kb}1.5Size in kilobytes
{size:mb}0.0Size in megabytes

Dates

VariableExample OutputDescription
{modified:relative}2 hours agoRelative time
{modified:short}1/24/25Short date format
{modified:long}January 24, 2025Long date format
{modified:iso}2025-01-24T10:30:00ISO 8601 format
{created:relative}3 days agoFile creation date

Text Formatting

Append :upper, :lower, or :title to text variables:

VariableExample Output
{filename:upper}SCRIPT.PY
{filename:lower}script.py
{filename:title}Script.Py

Inline Code

For short code snippets, use the ~~~ separator instead of META.PATH:

```ufence-python
META:
  TITLE: "Quick Example"
~~~
def hello():
    print("Hello!")
```

Everything before ~~~ is YAML configuration; everything after is code.

PROMPT Regex Patterns

The STYLE.PROMPT property uses a regex with two capture groups to identify command lines:

  • Group 1: The prompt (displayed with prompt styling)
  • Group 2: The command (displayed with command styling)

Lines that don't match are treated as output.

Common Patterns

PatternMatches
^(\\$ )(.*)$ command
^(> )(.*)> command
^(>>> )(.*)>>> command (Python REPL)
^(.*\\$ )(.*)user@host:~$ command
^(\\[.*?\\] -> )(.*)[status] -> command
^(.*@.*:\\S+ \\$ )(.*)user@hostname:/path $ command

Note: Backslashes must be doubled in YAML strings.

Examples

Basic file embed

```ufence-python
META:
  PATH: "vault://scripts/utils.py"
```

With line filtering

```ufence-javascript
META:
  PATH: "vault://src/app.js"
  TITLE: "Main function"
FILTER:
  BY_LINES:
    RANGE: 10, 25
```

With marker extraction

```ufence-python
META:
  PATH: "vault://code/example.py"
  TITLE: "Configuration Section"
FILTER:
  BY_MARKS:
    START: "# BEGIN CONFIG"
    END: "# END CONFIG"
    INCLUSIVE: false
```

Minimal style with line numbers

```ufence-bash
META:
  PATH: "vault://scripts/deploy.sh"
RENDER:
  STYLE: "minimal"
  LINES: true
```

Folded code block

```ufence-sql
META:
  PATH: "vault://queries/report.sql"
  DESC: "Click to expand full query"
RENDER:
  FOLD: 5
```

Scrollable code block

```ufence-java
META:
  PATH: "vault://src/Main.java"
RENDER:
  SCROLL: 15
```

Inline code with all options

```ufence-python
META:
  TITLE: "Quick Sort"
  DESC: "Recursive implementation"
RENDER:
  STYLE: "infobar"
  LINES: true
  ZEBRA: true
~~~
def quicksort(arr):
    if len(arr) <= 1:
        return arr
    pivot = arr[len(arr) // 2]
    left = [x for x in arr if x < pivot]
    middle = [x for x in arr if x == pivot]
    right = [x for x in arr if x > pivot]
    return quicksort(left) + middle + quicksort(right)
```

Filter chaining: lines then markers

```ufence-typescript
META:
  PATH: "vault://src/config.ts"
  TITLE: "Database Config"
FILTER:
  BY_LINES:
    RANGE: 50, 200
  BY_MARKS:
    START: "// DATABASE_START"
    END: "// DATABASE_END"
```

Command output with custom styling

```ufence-cmdout
META:
  TITLE: "Deployment Log"
PROMPT: "^(\\[.*?\\] -> )(.*)"
RENDER:
  PROMPT:
    COLOUR: "#888888"
  COMMAND:
    COLOUR: "#61afef"
    BOLD: true
~~~
[OK] -> ./deploy.sh
Deploying to production...
Done!
[OK] -> ./verify.sh
All checks passed.
```

Remote file

```ufence-javascript
META:
  PATH: "https://raw.githubusercontent.com/user/repo/main/index.js"
  TITLE: "Remote Example"
```

Title Styles

tab (default)

A file tab sitting above the code block, similar to IDE tabs.

integrated

Full-width header that blends into the code block with no gap.

minimal

Small, understated, semi-transparent label.

infobar

Full-width bar with accent border and right-aligned metadata.

none

No title bar displayed.

Icon Styles

emoji

Language-specific emoji icons: Python shows snake, Bash shows scroll, SQL shows filing cabinet, etc.

text

Short text labels: PY, SH, SQL, JS, etc.

filled

Coloured boxes with language abbreviations.

outline

Theme-aware outlined boxes with language abbreviations.

custom

Load icons from a vault folder. Place files named {language}.svg, {language}.png, etc. in the configured icon folder.

none

No icons displayed.

Download Button

Code blocks can include a download button that saves the content to a file. Enable it in Settings (Code tab) with the Download button toggle.

On desktop, clicking the button opens a native OS save dialog. Obsidian remembers the last directory used for each note, so subsequent downloads default to the same location. On mobile, the button triggers a standard browser download.

The suggested filename is derived from the title (if set) with the language as the extension. For example, a block with TITLE: "deploy" in ufence-bash suggests deploy.bash. If no title is provided, the default is code.{lang}.

Presets & Page Defaults

Presets let you define reusable YAML configurations that can be referenced by name across multiple code blocks.

Creating a preset

Open Settings → Ultra Code Fence → Presets tab. Give your preset a name and enter the YAML config it should contain (using the same RENDER:, META:, FILTER: structure as a regular block).

Using a preset in a block

Reference a preset by name under META.PRESET:

META:
  PRESET: "teaching"
  TITLE: "My Override Title"
RENDER:
  ZEBRA: false

Block-level properties always take priority over preset values, so you can override individual settings as needed.

Page-level defaults with ufence-ufence

You can set defaults for every ufence block on a page by adding an invisible ufence-ufence config block:

```ufence-ufence
RENDER:
  ZEBRA: true
  LINES: true
```

The block is hidden in the rendered view. All ufence blocks on the same page inherit these defaults (unless they override them individually). Only one ufence-ufence block is supported per page.

You can also reference a named preset at page level:

```ufence-ufence
PRESET: "teaching"
```

Refreshing after changes

Changes to a ufence-ufence block or to a saved preset do not update existing code blocks automatically. To see your changes, use the Force Refresh command:

Command paletteUltra Code Fence: Force refresh all code blocks

You can assign a hotkey to this command in Settings → Hotkeys for quicker access. Preset changes made via the Settings UI apply automatically when you click Save.

Keyboard Shortcuts

  • Click title: Open source file (vault files open in Obsidian; URLs open in browser)
  • Ctrl/Cmd + Click title: Open vault file in new pane
  • Click copy button: Copy code to clipboard
  • Click download button: Save code to file
  • Click fold button: Expand/collapse code block

CSS Classes

For custom styling, the plugin uses these CSS class prefixes:

  • .ucf - Main container
  • .ucf-title - Title bar
  • .ucf-code - Code block
  • .ucf-line - Individual lines
  • .ucf-cmdout-* - Command output elements

Licence

MIT

Credits

  • Original embed-code-file plugin by Abdullah Almariah
  • Modernised and extended by Rachel Ambler

Demo Screenshots

See Demos.md for visual examples of the plugin's features.

For plugin developers

Search results and similarity scores are powered by semantic analysis of your plugin's README. If your plugin isn't appearing for searches you'd expect, try updating your README to clearly describe your plugin's purpose, features, and use cases.