eleventy
eleventy copied to clipboard
How to create a page from multiple .md, .html, .js files
I'm trying to create a set of example pages where each page might consist of a .md, .html, and .js file. The .html and .js files are the example content and need to be both included into the content of the page and included into the source of the page. These are runnable examples.
docs/
└─examples/
├─ example-1.md
├─ example-1.html
├─ example-1.js
└─ example-2...
And this should generate one .html file per example:
_site/
└─examples/
├─ example-1.html
└─ example-2.html
So far, I can include the .html and .js files with a template system include, and I can prevent the entire directory from being output with a examples.json file that sets permalink to false, but I can't figure out how to set permalink to false only for the .html files and use the default for the .md file.
I might be able to do something here with collections and pagination, where I set permalink to false for the entire directory, but create a examples.11ty.js file that then outputs one file per .md file, but that feels a bit convoluted.
Any recommendations here?
What about if you have:
docs/
└─examples/
├─ examples.json # sets directory-wide `permalink: false`, like you said.
|
├─ example-1.md # overrides template w/ `permalink: "examples/example-1.html"` or ...
├─ example-1.html
├─ example-1.js
|
├─ example-2.md # same `permalink: "examples/example-2.html"` override as above.
├─ example-2.html
├─ example-2.js
|
└─ example-3...
Was trying to figure out if it'd be easier to move all the *.html and *.js files into your _includes/ directory and manage them there, but then I guess that might split up the files and maybe you didn't want that.
My first thought is to change the extensions. But I'm not clear what your full requirements are. I haven't tested it, but something like:
docs/ └─examples/ ├─ example-1.md ├─ example-1.html.ins ├─ example-1.js.ins └─ example-2...
So, "ins" as in "insert". Theoretically they won't be handled as template or data files, and the outputs should be based on the *.md files. I'm assuming the md uses a layout file.
Again, this is all just a wild guess.
I posted my hacky example at https://github.com/pdehaan/11ty-includes-test
Not sure if I needed the permalink: false in the ./docs/examples/examples.11tydata.js file, or if I could just get away with setting the templateFormats: ["md", "njk"] in the root .eleventy.js config file, but it seems to build like expected.
Depending on the number of examples and includes you have, it might be easier to add one more level of nesting so it's ./docs/examples/example-1/ and then that directory includes as many .html, .js, .css, .png files as you need for a specific example (versus potentially one directory with dozens/hundreds of files).
Based on your description, here is a solution I tested. It adds an extra step of adding an extension to the files being inserted, so that they are not rendered as templates, and setting permalinks to false is not needed. It also uses a Nunjucks layout file.
Create a new Eleventy project.
Create the .eleventy.js file :
module.exports = {
templateFormats: ["njk", "md", "html", "js"]
};
Create two MD files :
test01.md
--- title: test01 layout: layout.njk htmlinsert: test01.html.ins jsinsert: test01.js.ins --- # Test 01 Test for insertion 01
test02.md
--- title: test02 layout: layout.njk htmlinsert: test02.html.ins jsinsert: test02.js.ins --- # Test 02 Test for insertion 02
Create the HTML files (for insertion) :
test01.html.ins
<button>test button 01</button> <p> test 01 </p>
test02.html.ins
<button>test button 02</button> <p> test 02 </p>
Create the JS files (for insertion) :
test01.js.ins
console.log('test 01');
test02.js.ins
console.log('test 02');
Create the layout file that is called for in the MD files' front matter :
_includes/layout.njk
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>{{ title }}</title>
</head>
<body>
{{ content | safe }}
<h3>
{{ htmlinsert }}
</h3>
{% include htmlinsert -%}
<h3>
{{ jsinsert }}
</h3>
<pre><code>
{% include jsinsert -%}
</code></pre>
</body>
</html>
What is going on here is the MD files supply the unique paths for the HTML and JS files to be inserted into each resulting page. Nunjucks can use those values in the include statements.
And since Eleventy is only looking for NJK, MD, HTML, and JS files as templates, it is ignoring the .INS files. The advantage of using .INS is that it doesn't interfere with using HTML or JS files elsewhere, and it makes it clear what the roles of those file are.
The resulting folder structure should be :
_site/
├test01
│ └index.html
└test02
└index.html
And _site/test01/index.html should contain :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>test01</title>
</head>
<body>
<h1>Test 01</h1>
<p>Test for insertion 01</p>
<h3>
test01.html.ins
</h3>
<button>test button 01</button>
<p>
test 01
</p>
<h3>
test01.js.ins
</h3>
<pre><code>
console.log('test 01');
</code></pre>
</body>
</html>
Note of course that for the HTML samples in the index.html page to display as code, you'll probably need to add a filter that converts it to character entities. But that's a separate question.
Some overlap with enhancement requests at https://github.com/11ty/eleventy/discussions/4116 and https://github.com/11ty/eleventy/discussions/3980
I’d acknowledge that we don’t have a super smooth option currently, but those are the best ideas to improve things moving forward!