Skip to content

Commit

Permalink
Merge pull request #30 from photogabble/patch/v1.1.0/#28
Browse files Browse the repository at this point in the history
BUGFIX: Pages Excluded from Collections
  • Loading branch information
carbontwelve authored May 2, 2024
2 parents d55e8cb + ce56d0e commit 3b11b5b
Show file tree
Hide file tree
Showing 8 changed files with 94 additions and 26 deletions.
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,
}

0 comments on commit 3b11b5b

Please sign in to comment.