gatsby-remark-embed-snippet is a Gatsby remark plugin that enables developers to embed formatted code snippets from external files directly into markdown content. It provides comprehensive support for file embedding through simple markdown syntax, advanced line selection, syntax highlighting integration with Prism.js, and snippet naming for referencing specific code sections.
npm install gatsby-remark-embed-snippet gatsby-remark-prismjs gatsby-transformer-remark prismjsThis package is configured as a Gatsby plugin rather than directly imported:
// gatsby-config.js
module.exports = {
plugins: [
{
resolve: `gatsby-transformer-remark`,
options: {
plugins: [
{
resolve: `gatsby-remark-embed-snippet`,
options: {
directory: `${__dirname}/snippets/`, // optional
},
},
{
resolve: `gatsby-remark-prismjs`,
options: {},
},
],
},
},
],
}After configuration, use inline code syntax in markdown files to embed code snippets:
# Sample JavaScript
`embed:javascript-code.js`
# Sample HTML
`embed:html-code.html`
# Embed specific lines
`embed:App.js#L6-8`
# Embed named snippet
`embed:api.js{snippet: "funcA"}`The main plugin function that processes markdown AST to embed code snippets.
/**
* Main plugin function that processes markdown AST to embed code snippets
* @param {object} params - Plugin parameters
* @param {object} params.markdownAST - The markdown Abstract Syntax Tree to process
* @param {object} params.markdownNode - The markdown node object containing file metadata
* @param {string} params.markdownNode.fileAbsolutePath - Absolute path to the markdown file
* @param {object} options - Plugin configuration options
* @param {string} [options.directory] - Directory path where code snippet files are located
* @returns {object} The modified markdownAST object
*/
module.exports = function ({ markdownAST, markdownNode }, { directory } = {}) {
// Implementation processes markdown AST and returns modified AST
return markdownAST;
}Embed entire file content using the embed:filename.ext syntax.
Markdown Syntax:
`embed:filename.ext`Example:
`embed:hello-world.js`
`embed:styles.css`
`embed:config.json`Embed specific lines from files using line number specifications.
Markdown Syntax:
embed:filename.ext#L1 - Single lineembed:filename.ext#L1-5 - Line rangeembed:filename.ext#L1-3,7-9 - Non-consecutive rangesExamples:
`embed:App.js#L6`
`embed:App.js#L6-8`
`embed:App.js#L2-4,7-9`Embed content between start-snippet{name} and end-snippet{name} comments.
Markdown Syntax:
`embed:filename.ext{snippet: "snippetName"}`Example:
`embed:api.js{snippet: "funcA"}`Source File Example:
// start-snippet{funcA}
function factorial(x) {
if (x <= 1) return 1;
else return x * factorial(x - 1);
}
// end-snippet{funcA}
function display() {
let x = 5;
// start-snippet{invokeA}
let xfact = factorial(x);
// end-snippet{invokeA}
console.log(`${x} factorial is ${xfact}`);
}Specify ranges of lines to be hidden from embedded files using hide-range comments.
JavaScript Example:
// hide-range{1-2}
import React from "react"
import ReactDOM from "react-dom"
function App() {
return (
<div className="App">
<ul>
<li>Not hidden</li>
<li>Not hidden</li>
{/* hide-range{1-2} */}
<li>Hidden</li>
<li>Hidden</li>
{/* hide-next-line */}
<li>Hidden</li>
</ul>
</div>
)
}
// hide-range{1-2}
const rootElement = document.getElementById("root")
ReactDOM.render(<App />, rootElement)Result:
function App() {
return (
<div className="App">
<ul>
<li>Not hidden</li>
<li>Not hidden</li>
</ul>
</div>
)
}Automatic syntax highlighting language detection based on file extensions.
/**
* File extension to language mapping for Prism.js syntax highlighting
*/
const FILE_EXTENSION_TO_LANGUAGE_MAP = {
js: `jsx`,
md: `markup`,
sh: `bash`,
rb: `ruby`,
rs: `rust`,
py: `python`,
ps1: `powershell`,
psm1: `powershell`,
bat: `batch`,
h: `c`,
tex: `latex`,
csproj: `xml`,
}
/**
* Determines programming language from file extension for syntax highlighting
* @param {string} file - File name or path
* @returns {string} Language identifier string for Prism.js syntax highlighting
*/
const getLanguage = file => {
if (!file.includes(`.`)) {
return `none`
}
const extension = file.split(`.`).pop()
return FILE_EXTENSION_TO_LANGUAGE_MAP.hasOwnProperty(extension)
? FILE_EXTENSION_TO_LANGUAGE_MAP[extension]
: extension.toLowerCase()
}Supported File Extensions:
.js → jsx.md → markup.sh → bash.rb → ruby.rs → rust.py → python.ps1, .psm1 → powershell.bat → batch.h → c.tex → latex.csproj → xmlPlugin configuration options for customizing behavior.
interface PluginOptions {
/** Directory path where code snippet files are located */
directory?: string;
}Directory Option:
string (optional)Configuration Examples:
// Root directory
{
resolve: `gatsby-remark-embed-snippet`,
options: {
directory: `${__dirname}`
}
}
// Custom snippets directory
{
resolve: `gatsby-remark-embed-snippet`,
options: {
directory: `${__dirname}/snippets/`
}
}The plugin provides comprehensive error handling for common failure scenarios.
Error Types:
Invalid Directory Error
Invalid directory specified "${directory}"Invalid File Path Error
Invalid snippet specified; no such file "${snippetPath}"Invalid Snippet Options Error
Invalid snippet options specified: ${optionStr}The plugin requires several runtime and peer dependencies.
Runtime Dependencies:
@babel/runtime ^7.20.13 - Babel runtime helpersnormalize-path ^3.0.0 - Cross-platform path normalizationparse-numeric-range ^1.3.0 - Numeric range parsing (e.g. "1-3,7-9")unist-util-map ^2.0.1 - AST node traversal utilityPeer Dependencies:
gatsby ^5.0.0-next - Gatsby frameworkgatsby-remark-prismjs ^7.0.0-next - Prism.js syntax highlightingImportant Configuration Notes:
gatsby-remark-prismjs in the plugins arraygatsby-transformer-remark as the parent plugin