Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BUGFIX: Pages Excluded from Collections #30

Merged
merged 3 commits into from
May 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,11 @@ module.exports = (eleventyConfig) => {

### Internal Links / Wikilinks

This plugin will now parse all Wiki Links formatted for example, `[[Eleventy.js Interlink Plugin]]` appears as [Eleventy.js Interlink Plugin](https://photogabble.co.uk/projects/eleventyjs-interlink-plugin/).
This plugin will parse both Wikilinks and internal anchor links. The Wikilink format is a **page reference** wrapped in double square brackets, for example: `[[Eleventy.js Interlink Plugin]]` will appear as [Eleventy.js Interlink Plugin](https://photogabble.co.uk/projects/eleventyjs-interlink-plugin/).

Using the vertical bar (`|`) you can change the text used to display a link. This can be useful when you want to work a link into a sentence without using the title of the file, for example: `[[Eleventy.js Interlink Plugin|custom display text]]` appears as [custom display text](https://www.photogabble.co.uk/projects/eleventyjs-interlink-plugin/).

> NOTE: By default this plugin will use the `title` front-matter attribute of your pages or one of the aliases (as detailed below).
> **NOTE**: By default this plugin will use the `title` front-matter attribute of your pages or one of the aliases (as detailed below) as the **page reference**.

### Aliases

Expand Down Expand Up @@ -144,6 +144,10 @@ You can then display this information in any way you would like, I use the below
{% endif %}
```

### Pages Excluded from Collections

Due to how this plugin obtains a pages template content, all pages with `eleventyExcludeFromCollections:true` set will **NOT** be parsed by the interlinker.

## Known Caveats

- This plugin doesn't implement all [Obsidians wikilink support](https://help.obsidian.md/Linking+notes+and+files/Internal+links) for example linking to a block in a note and linking to a heading in a note is not currently supported by this plugin
Expand Down
5 changes: 3 additions & 2 deletions src/interlinker.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ module.exports = class Interlinker {
const dependencies = [data.title, data.page, data.collections.all];
if (dependencies[0] === undefined || !dependencies[1].inputPath || dependencies[2].length === 0) return [];

this.deadLinks.setFileSrc(data.page.inputPath);

const {slugifyFn} = this.opts;

const compilePromises = [];
Expand All @@ -98,8 +100,7 @@ module.exports = class Interlinker {
const currentSlug = slugifyFn(data.title);
let currentSlugs = new Set([currentSlug, data.page.fileSlug]);
const currentPage = pageDirectory.findByFile(data);

this.deadLinks.setFileSrc(currentPage.inputPath);
if (!currentPage) return [];

// Populate our link map for use later in replacing WikiLinks with page permalinks.
// Pages can list aliases in their front matter, if those exist we should map them
Expand Down
57 changes: 35 additions & 22 deletions tests/eleventy.test.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
const Eleventy = require("@11ty/eleventy");
const path = require('node:path');
const {normalize} = require('./helpers');
const sinon = require('sinon');
const {normalize, consoleMockMessages, findResultByUrl, fixturePath} = require('./helpers');
const test = require("ava");
const sinon = require("sinon");

function findResultByUrl(results, url) {
const [result] = results.filter(result => result.url === url);
return result;
}

const fixturePath = (p) => path.normalize(path.join(__dirname, 'fixtures', p));
// NOTE: Tests using sinon to mock console.warn need to be run with
// `test.serial` so that they don't run at the same time as one another to
// avoid the "Attempted to wrap warn which is already wrapped" error.
// @see https://stackoverflow.com/a/37900956/1225977

test("Sample page (wikilinks and regular links)", async t => {
let elev = new Eleventy(fixturePath('sample-small-website'), fixturePath('sample-small-website/_site'), {
Expand All @@ -31,25 +29,15 @@ test("Sample page (wikilinks and regular links)", async t => {
);
});

test("Broken page (wikilinks and regular links)", async t => {
const messages = [];
const consoleStub = sinon.stub(console, 'warn').callsFake(msg => messages.push());
test.serial("Broken page (wikilinks and regular links)", async t => {
const mock = sinon.stub(console, 'warn');

let elev = new Eleventy(fixturePath('website-with-broken-links'), fixturePath('website-with-broken-links/_site'), {
configPath: fixturePath('website-with-broken-links/eleventy.config.js'),
});

let results = await elev.toJSON();

let logLines = [];
for (let i = 0; i < consoleStub.callCount; i++) {
const line = normalize(consoleStub.getCall(i).args.join(' '))
// Sometimes 11ty will output benchmark info, failing the test randomly.
if (line.includes('[11ty]')) continue;
logLines.push(line);
}

consoleStub.restore();
mock.restore();

// Markdown will have the link href set to /stubs
t.is(
Expand All @@ -63,7 +51,7 @@ test("Broken page (wikilinks and regular links)", async t => {
`<div>This is to show that we can identify <a href="/broken">broken <em>internal</em> links</a>.</div>`
);

t.is(logLines.length, 4, 'console.warn should be called three times');
t.is(consoleMockMessages(mock).length, 4, 'console.warn should be called four times');
});

test("Sample page (markdown with embed)", async t => {
Expand All @@ -85,3 +73,28 @@ test("Sample page (markdown with embed)", async t => {
`<div><p><p>Hello world.</p></p></div><div></div>`
);
});

test.serial("Sample page (eleventyExcludeFromCollections set true)", async t => {
const mock = sinon.stub(console, 'warn');

let elev = new Eleventy(fixturePath('sample-with-excluded-file'), fixturePath('sample-with-excluded-file/_site'), {
configPath: fixturePath('sample-with-excluded-file/eleventy.config.js'),
});

let results = await elev.toJSON();

mock.restore();
t.is(consoleMockMessages(mock).length, 2, 'console.warn should be called twice');

// Embedded page is aware of its embedding
t.is(
normalize(findResultByUrl(results, '/about/').content),
`<div><p>This wikilink to <a href="/stubs">something</a> will not parse because the destination has eleventyExcludeFromCollections set true.</p></div><div></div>`
);

// Embed shows
t.is(
normalize(findResultByUrl(results, '/').content),
`<div><p>Hello World, no links, wiki or otherwise will be parsed by the interlinker due to being excluded from collections.</p></div><div></div>`
);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<div>{{ content }}</div>
<div>{%- for link in backlinks %}<a href="{{ link.url }}">{{ link.title }}</a>{%- endfor %}</div>
6 changes: 6 additions & 0 deletions tests/fixtures/sample-with-excluded-file/about.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
title: About
layout: default.liquid
---

This wikilink to [[something]] will not parse because the destination has eleventyExcludeFromCollections set true.
12 changes: 12 additions & 0 deletions tests/fixtures/sample-with-excluded-file/eleventy.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module.exports = function (eleventyConfig) {
eleventyConfig.addPlugin(
require('../../../index.js'),
);

return {
dir: {
includes: "_includes",
layouts: "_layouts",
}
}
}
7 changes: 7 additions & 0 deletions tests/fixtures/sample-with-excluded-file/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
title: Something
layout: default.liquid
eleventyExcludeFromCollections: true
---

Hello World, no links, wiki or otherwise will be parsed by the interlinker due to being excluded from collections.
23 changes: 23 additions & 0 deletions tests/helpers.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,30 @@
const path = require("node:path");

function normalize(str) {
return str.trim().replace(/\r?\n|\r/g, '');
}

function consoleMockMessages(mock) {
let logLines = [];
for (let i = 0; i < mock.callCount; i++) {
const line = normalize(mock.getCall(i).args.join(' '))
// Sometimes 11ty will output benchmark info, failing the test randomly.
if (line.includes('[11ty]')) continue;
logLines.push(line);
}
return logLines;
}

function findResultByUrl(results, url) {
const [result] = results.filter(result => result.url === url);
return result;
}

const fixturePath = (p) => path.normalize(path.join(__dirname, 'fixtures', p));

module.exports = {
normalize,
consoleMockMessages,
findResultByUrl,
fixturePath,
}
Loading