feat: introduce Expressive Code for code block rendering (#476)
* feat: improve code block feature with Expressive Code * docs: add example Markdown file for visual review * feat: improve styles of Expressive Code * fix: errors from the merging * chore: formatting * chore: update config * chore: update dependencies * fix: fix build error * fix: minor fixes * fix: style tweaks * docs: update example post * fix: isolate copy button timeouts to avoid cross-button interference --------- Co-authored-by: Hasenpfote <Hasenpfote36@gmail.com>
This commit is contained in:
@@ -0,0 +1,311 @@
|
||||
---
|
||||
title: Expressive Code Example
|
||||
published: 2024-04-10
|
||||
description: How code blocks look in Markdown using Expressive Code.
|
||||
tags: [Markdown, Blogging, Demo]
|
||||
category: Examples
|
||||
draft: false
|
||||
---
|
||||
|
||||
Here, we'll explore how code blocks look using [Expressive Code](https://expressive-code.com/). The provided examples are based on the official documentation, which you can refer to for further details.
|
||||
|
||||
## Expressive Code
|
||||
|
||||
### Syntax Highlighting
|
||||
|
||||
[Syntax Highlighting](https://expressive-code.com/key-features/syntax-highlighting/)
|
||||
|
||||
#### Regular syntax highlighting
|
||||
|
||||
```js
|
||||
console.log('This code is syntax highlighted!')
|
||||
```
|
||||
|
||||
#### Rendering ANSI escape sequences
|
||||
|
||||
```ansi
|
||||
ANSI colors:
|
||||
- Regular: [31mRed[0m [32mGreen[0m [33mYellow[0m [34mBlue[0m [35mMagenta[0m [36mCyan[0m
|
||||
- Bold: [1;31mRed[0m [1;32mGreen[0m [1;33mYellow[0m [1;34mBlue[0m [1;35mMagenta[0m [1;36mCyan[0m
|
||||
- Dimmed: [2;31mRed[0m [2;32mGreen[0m [2;33mYellow[0m [2;34mBlue[0m [2;35mMagenta[0m [2;36mCyan[0m
|
||||
|
||||
256 colors (showing colors 160-177):
|
||||
[38;5;160m160 [38;5;161m161 [38;5;162m162 [38;5;163m163 [38;5;164m164 [38;5;165m165[0m
|
||||
[38;5;166m166 [38;5;167m167 [38;5;168m168 [38;5;169m169 [38;5;170m170 [38;5;171m171[0m
|
||||
[38;5;172m172 [38;5;173m173 [38;5;174m174 [38;5;175m175 [38;5;176m176 [38;5;177m177[0m
|
||||
|
||||
Full RGB colors:
|
||||
[38;2;34;139;34mForestGreen - RGB(34, 139, 34)[0m
|
||||
|
||||
Text formatting: [1mBold[0m [2mDimmed[0m [3mItalic[0m [4mUnderline[0m
|
||||
```
|
||||
|
||||
### Editor & Terminal Frames
|
||||
|
||||
[Editor & Terminal Frames](https://expressive-code.com/key-features/frames/)
|
||||
|
||||
#### Code editor frames
|
||||
|
||||
```js title="my-test-file.js"
|
||||
console.log('Title attribute example')
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
```html
|
||||
<!-- src/content/index.html -->
|
||||
<div>File name comment example</div>
|
||||
```
|
||||
|
||||
#### Terminal frames
|
||||
|
||||
```bash
|
||||
echo "This terminal frame has no title"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
```powershell title="PowerShell terminal example"
|
||||
Write-Output "This one has a title!"
|
||||
```
|
||||
|
||||
#### Overriding frame types
|
||||
|
||||
```sh frame="none"
|
||||
echo "Look ma, no frame!"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
```ps frame="code" title="PowerShell Profile.ps1"
|
||||
# Without overriding, this would be a terminal frame
|
||||
function Watch-Tail { Get-Content -Tail 20 -Wait $args }
|
||||
New-Alias tail Watch-Tail
|
||||
```
|
||||
|
||||
### Text & Line Markers
|
||||
|
||||
[Text & Line Markers](https://expressive-code.com/key-features/text-markers/)
|
||||
|
||||
#### Marking full lines & line ranges
|
||||
|
||||
```js {1, 4, 7-8}
|
||||
// Line 1 - targeted by line number
|
||||
// Line 2
|
||||
// Line 3
|
||||
// Line 4 - targeted by line number
|
||||
// Line 5
|
||||
// Line 6
|
||||
// Line 7 - targeted by range "7-8"
|
||||
// Line 8 - targeted by range "7-8"
|
||||
```
|
||||
|
||||
#### Selecting line marker types (mark, ins, del)
|
||||
|
||||
```js title="line-markers.js" del={2} ins={3-4} {6}
|
||||
function demo() {
|
||||
console.log('this line is marked as deleted')
|
||||
// This line and the next one are marked as inserted
|
||||
console.log('this is the second inserted line')
|
||||
|
||||
return 'this line uses the neutral default marker type'
|
||||
}
|
||||
```
|
||||
|
||||
#### Adding labels to line markers
|
||||
|
||||
```jsx {"1":5} del={"2":7-8} ins={"3":10-12}
|
||||
// labeled-line-markers.jsx
|
||||
<button
|
||||
role="button"
|
||||
{...props}
|
||||
value={value}
|
||||
className={buttonClassName}
|
||||
disabled={disabled}
|
||||
active={active}
|
||||
>
|
||||
{children &&
|
||||
!active &&
|
||||
(typeof children === 'string' ? <span>{children}</span> : children)}
|
||||
</button>
|
||||
```
|
||||
|
||||
#### Adding long labels on their own lines
|
||||
|
||||
```jsx {"1. Provide the value prop here:":5-6} del={"2. Remove the disabled and active states:":8-10} ins={"3. Add this to render the children inside the button:":12-15}
|
||||
// labeled-line-markers.jsx
|
||||
<button
|
||||
role="button"
|
||||
{...props}
|
||||
|
||||
value={value}
|
||||
className={buttonClassName}
|
||||
|
||||
disabled={disabled}
|
||||
active={active}
|
||||
>
|
||||
|
||||
{children &&
|
||||
!active &&
|
||||
(typeof children === 'string' ? <span>{children}</span> : children)}
|
||||
</button>
|
||||
```
|
||||
|
||||
#### Using diff-like syntax
|
||||
|
||||
```diff
|
||||
+this line will be marked as inserted
|
||||
-this line will be marked as deleted
|
||||
this is a regular line
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
```diff
|
||||
--- a/README.md
|
||||
+++ b/README.md
|
||||
@@ -1,3 +1,4 @@
|
||||
+this is an actual diff file
|
||||
-all contents will remain unmodified
|
||||
no whitespace will be removed either
|
||||
```
|
||||
|
||||
#### Combining syntax highlighting with diff-like syntax
|
||||
|
||||
```diff lang="js"
|
||||
function thisIsJavaScript() {
|
||||
// This entire block gets highlighted as JavaScript,
|
||||
// and we can still add diff markers to it!
|
||||
- console.log('Old code to be removed')
|
||||
+ console.log('New and shiny code!')
|
||||
}
|
||||
```
|
||||
|
||||
#### Marking individual text inside lines
|
||||
|
||||
```js "given text"
|
||||
function demo() {
|
||||
// Mark any given text inside lines
|
||||
return 'Multiple matches of the given text are supported';
|
||||
}
|
||||
```
|
||||
|
||||
#### Regular expressions
|
||||
|
||||
```ts /ye[sp]/
|
||||
console.log('The words yes and yep will be marked.')
|
||||
```
|
||||
|
||||
#### Escaping forward slashes
|
||||
|
||||
```sh /\/ho.*\//
|
||||
echo "Test" > /home/test.txt
|
||||
```
|
||||
|
||||
#### Selecting inline marker types (mark, ins, del)
|
||||
|
||||
```js "return true;" ins="inserted" del="deleted"
|
||||
function demo() {
|
||||
console.log('These are inserted and deleted marker types');
|
||||
// The return statement uses the default marker type
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
### Word Wrap
|
||||
|
||||
[Word Wrap](https://expressive-code.com/key-features/word-wrap/)
|
||||
|
||||
#### Configuring word wrap per block
|
||||
|
||||
```js wrap
|
||||
// Example with wrap
|
||||
function getLongString() {
|
||||
return 'This is a very long string that will most probably not fit into the available space unless the container is extremely wide'
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
```js wrap=false
|
||||
// Example with wrap=false
|
||||
function getLongString() {
|
||||
return 'This is a very long string that will most probably not fit into the available space unless the container is extremely wide'
|
||||
}
|
||||
```
|
||||
|
||||
#### Configuring indentation of wrapped lines
|
||||
|
||||
```js wrap preserveIndent
|
||||
// Example with preserveIndent (enabled by default)
|
||||
function getLongString() {
|
||||
return 'This is a very long string that will most probably not fit into the available space unless the container is extremely wide'
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
```js wrap preserveIndent=false
|
||||
// Example with preserveIndent=false
|
||||
function getLongString() {
|
||||
return 'This is a very long string that will most probably not fit into the available space unless the container is extremely wide'
|
||||
}
|
||||
```
|
||||
|
||||
## Collapsible Sections
|
||||
|
||||
[Collapsible Sections](https://expressive-code.com/plugins/collapsible-sections/)
|
||||
|
||||
```js collapse={1-5, 12-14, 21-24}
|
||||
// All this boilerplate setup code will be collapsed
|
||||
import { someBoilerplateEngine } from '@example/some-boilerplate'
|
||||
import { evenMoreBoilerplate } from '@example/even-more-boilerplate'
|
||||
|
||||
const engine = someBoilerplateEngine(evenMoreBoilerplate())
|
||||
|
||||
// This part of the code will be visible by default
|
||||
engine.doSomething(1, 2, 3, calcFn)
|
||||
|
||||
function calcFn() {
|
||||
// You can have multiple collapsed sections
|
||||
const a = 1
|
||||
const b = 2
|
||||
const c = a + b
|
||||
|
||||
// This will remain visible
|
||||
console.log(`Calculation result: ${a} + ${b} = ${c}`)
|
||||
return c
|
||||
}
|
||||
|
||||
// All this code until the end of the block will be collapsed again
|
||||
engine.closeConnection()
|
||||
engine.freeMemory()
|
||||
engine.shutdown({ reason: 'End of example boilerplate code' })
|
||||
```
|
||||
|
||||
## Line Numbers
|
||||
|
||||
[Line Numbers](https://expressive-code.com/plugins/line-numbers/)
|
||||
|
||||
### Displaying line numbers per block
|
||||
|
||||
```js showLineNumbers
|
||||
// This code block will show line numbers
|
||||
console.log('Greetings from line 2!')
|
||||
console.log('I am on line 3')
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
```js showLineNumbers=false
|
||||
// Line numbers are disabled for this block
|
||||
console.log('Hello?')
|
||||
console.log('Sorry, do you know what line I am on?')
|
||||
```
|
||||
|
||||
### Changing the starting line number
|
||||
|
||||
```js showLineNumbers startLineNumber=5
|
||||
console.log('Greetings from line 5!')
|
||||
console.log('I am on line 6')
|
||||
```
|
||||
Reference in New Issue
Block a user