![PyPI Now Supports iOS and Android Wheels for Mobile Python Development](https://cdn.sanity.io/images/cgdhsj6q/production/96416c872705517a6a65ad9646ce3e7caef623a0-1024x1024.webp?w=400&fit=max&auto=format)
Security News
PyPI Now Supports iOS and Android Wheels for Mobile Python Development
PyPI now supports iOS and Android wheels, making it easier for Python developers to distribute mobile packages.
eleventy-plugin-outline
Advanced tools
This plugin is the swiss army knife when it comes to creating outlines in Eleventy, but it’s also quite opinionated in how it does things. It affords customization via extensibility, rather than configuration.
This plugin is the swiss army knife when it comes to creating outlines in Eleventy.
Features include:
<h1>
to <h3>
without an <h2>
)Use the outline
filter on any content you want to process.
The filter does double duty: it both picks up headings and figures from the content passed,
and adds this info to the HTML.
{{ content | outline | safe }}
By default, outlines are scoped to the output path (regardless of how many files it’s made up of). However, somtimes you want outlines to span multiple output paths, for example chapters in a book. To join up outlines across multiple output paths (or create multiple separate outlines within the same output path), you can use a scope argument:
{{ content | outline(scope) | safe }}
[!WARNING] Ids need to be unique within a scope. If they are not, they will be rewritten to be unique (and produce a warning), Any ids generated are also unique within the scope.
Once content is processed, you can read the (TODO) outline
global data objectoutlines[scope]
to render an outline for a specific scope.
If you did not specify a scope, it defaults to page.url
so outlines[page.url]
will contain the outline for the current page.
[!WARNING] This will only include outlines for content that has gone through the
outline
filter at the time of rendering.
When you have at most one scope per page,
cross-references will be processed automatically via an 11ty transform.
However, when you have multiple scopes within the same page,
we can’t know which references belong to which scope, so you need to process them manually with the xrefs
filter:
{{ content | xrefs(scope) | safe }}
[!WARNING] Cross-references to other files (for scopes that span multiple files) are not yet processed, but this is a high-priority planned feature.
The plugin tries to introduce as little syntax as possible.
References are simply empty links, e.g. [](#fig:myfigure)
in Markdown or <a href="#my-section-id"></a>
in HTML.
Even cross-references across files (for outlines that span multiple files) are just [](/path/to/file/#my-section-id)
.
Any headings will be picked up by the plugin unless excluded by the exclude
option (which takes a function).
If they already have ids (e.g. via something like markdown-it-anchor
), they will be preserved.
If they don’t, ids that are unique within the specified scope will be generated for them.
[!NOTE] In the future I’m hoping to add a way to exclude certain headings from the outline.
Just use a regular HTML <figure>
with an id.
This combines quite well with Markdown too, just make sure to leave a blank line between the <figure>
and <figcaption>
and their contents:
<figure id="my-figure">
![A diagram where…](figures/diagram.svg)
<figcaption>
Progression of _Foo_ over time
</figcaption>
</figure>
There are two ways to specify a table.
The recommended way is a <figure>
, which also combines nicely with Markdown:
<figure id="tab:my-table">
| Foo | Bar |
| --- | --- |
| 1 | 2 |
<figcaption>Table 1: Foo and Bar</figcaption>
</figure>
You don’t need to use a tab:
prefix in your id, the plugin will figure it out automatically
if all your figure contains is a table.
You can also use a raw <table>
with a <caption>
:
<table id="my-table">
<caption>Table 1: Foo and Bar</caption>
<thead>
<tr>
<th>Foo</th>
<th>Bar</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>2</td>
</tr>
</tbody>
</table>
Sometimes you may want to specify data explicitly. For example, for outlines that span multiple files, you have no control over the order the files are processed in, so you’ll end up with non-deterministic top-level numbers!
Or, if you are combining content from multiple files into a single file, cross-file references to the original files won't work correctly, because all this plugin can see is the URL of the current page.
To explicitly override things, you can use data-*
attributes on your headings:
data-number
to override the generated qualifiedNumber
data-label
to override the labeldata-url
to override the page URLThe outlines
global data is an Outlines
object,
and each actual outline is an Outline
object.
These objects have the structure below:
class OutlineItems extends Map<string, OutlineItem> {
parent: OutlineItem;
options: object;
countsByType: Map<string, number>;
get root ();
get numberSeparator ();
get qualifiedNumber ();
get firstValue ();
get lastValue ();
}
class OutlineItem {
parent: OutlineItems;
options: object;
// Each subclass defines this to a distinct value
// e.g. "heading" or "figure"
kind: string;
// Subtype, e.g. "chapter" or "appendix"
type: string;
id: string;
// Iff the id was rewritten to be unique, this will contain the original
originalId: string;
// HTML attributes as a string. This includes id.
attrs: string;
// The original HTML content of the element
content: string;
// The trimmed text content of with all elements stripped off
// For figures, this is the caption text
text: string;
// The full rendered HTML of the element
html: string;
// The original HTML of the element that was parsed
originalHTML: string;
// This section’s number (without parent numbers)
// E.g. for section 1.2.3, this would be 3
number: string;
// The full number, including parent numbers
qualifiedNumber: string;
// The parent section’s qualified number, plus the separator
qualifiedNumberPrefix: string;
// The textual index of this heading in the content processed
index: number;
// The page input path (e.g. "foo/index.md")
inputPath: string;
// The page output path (e.g. "dist/foo/index.html")
outputPath: string;
// The page URL (e.g. "/foo/")
url: string;
}
class Outline extends OutlineItems {
// Will return this if it contains more than one top-level section
// or the only top-level section if there is only one.
// This is mainly useful for displaying tables of contents.
get toc();
}
class Heading extends OutlineItem {
// The heading level (1-6)
level: number;
// Child headings
children: Outline;
// Figures in this section (but not in children)
figures: Figures;
}
class Figures extends OutlineItems {
}
class Figure extends OutlineItem {
}
npm install eleventy-plugin-outline
Then, in your Eleventy config:
import outline from 'eleventy-plugin-outline';
and add it to your Eleventy config:
eleventyConfig.addPlugin(outline, {
// Options
});
You can provide options to customize behavior. For details on the options available, check out the default options.
if you have any plugins generating ids, make sure they are included before this one.
FAQs
This plugin is the swiss army knife when it comes to creating outlines in Eleventy, but it’s also quite opinionated in how it does things. It affords customization via extensibility, rather than configuration.
The npm package eleventy-plugin-outline receives a total of 5 weekly downloads. As such, eleventy-plugin-outline popularity was classified as not popular.
We found that eleventy-plugin-outline demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
PyPI now supports iOS and Android wheels, making it easier for Python developers to distribute mobile packages.
Security News
Create React App is officially deprecated due to React 19 issues and lack of maintenance—developers should switch to Vite or other modern alternatives.
Security News
Oracle seeks to dismiss fraud claims in the JavaScript trademark dispute, delaying the case and avoiding questions about its right to the name.