diff --git a/.eleventy.js b/.eleventy.js index 2d93613..b4a373b 100644 --- a/.eleventy.js +++ b/.eleventy.js @@ -1,6 +1,7 @@ const Config = require("./src/Config"); const SEO = require("./src/SEO"); const Canonical = require("./src/Canonical"); +const MetaRobots = require("./src/MetaRobots"); module.exports = { configFunction: (eleventyConfig, options = {}) => { @@ -15,5 +16,10 @@ module.exports = { const canonical = new Canonical(liquidEngine, config); return canonical.getObject(); }); + + eleventyConfig.addLiquidTag("metaRobots", liquidEngine => { + const metaRobots = new MetaRobots(liquidEngine, config); + return metaRobots.getObject(); + }); } }; diff --git a/README.md b/README.md index 724588e..a79f2b9 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,11 @@ An [Eleventy](https://github.com/11ty/eleventy) plugin to generate meta tags for _I wrote this plugin when moving from Jekyll to Eleventy to get the functionality I previously had with Jekyll SEO Tag._ +## Features + +* Canonical URL. +* Robots meta directive for pagination. + ## Installation Available on [npm](https://www.npmjs.com/package/eleventy-plugin-seo): @@ -27,6 +32,16 @@ module.exports = function(eleventyConfig) { }; ``` +## Usage + +Add the following right before `` in your site's template(s): + +```liquid +{% seo %} +``` + +Done! + ## Config Pass in an object with config options to the plugin: @@ -47,27 +62,17 @@ eleventyConfig.addPlugin(pluginSEO, require("./src/_data/seo.json")); #### url -Full URL to the site, without trailing slash. Ie, `https://foo.com`. - -## Usage - -Add the following right before `` in your site's template(s): - -```liquid -{% seo %} -``` - -Done! +Full URL to the site without trailing slash, `https://foo.com`. ## Additional Tags -While adding the `seo` tag is all that is needed, the plugin defines more liquid tags that it uses internally that can be convenient to use in other places. +While adding the `{% seo %}` tag is all that is needed, the plugin defines more liquid tags that it uses internally that can be convenient to use in other places. -The following tags are supplied by the plugin. +The following liquid tags are supplied by the plugin. ### `canonicalURL [url]` -Uses: `site.url` +Generates the canonical URL for the current page or for another page if passing in an argument. ```liquid {% canonicalURL %} @@ -75,22 +80,43 @@ Uses: `site.url` {% canonicalURL post.url %} ``` -Use without arg to canonical url for current page -``` +Use without arg to canonical url for current page: + +```liquid ``` -Use with arg to link to a specific page, like feed.xml +Use with arg to link to a specific page, like feed.xml: ```liquid ``` -Use with eleventy data arg, like post.url that resolves to the current url in places like feed.liquid or sitemap.liquid +Use with Eleventy provided variables, like `page.url` that resolves to an url in places like... + +...feed.liquid: + +```liquid +{% for post in collections.posts limit: 10 %} + ... + {% canonicalURL post.url %} + ... +{% endfor %} +``` + +...sitemap.liquid: ```liquid -// from feed.liquid -{% canonicalURL post.url %} +{% for item in collections.all %} + ... + {% canonicalURL item.url %} + ... +{% endfor %} +``` + +### `metaRobots` -// from sitemap.liquid -{% canonicalURL item.url %} +Adds robots meta directive with `index,follow` except on paginated pages which gets `noindex,follow`. + +```liquid +{% metaRobots %} ``` diff --git a/package.json b/package.json index 043fa95..77ae370 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,15 @@ { "name": "eleventy-plugin-seo", - "version": "0.3.1", + "version": "0.3.2", "description": "Eleventy plugin to generate meta tags for improved SEO.", "main": ".eleventy.js", "scripts": { "check": "npx prettier --check 'src/**/*.js' 'test/**/*.js' .eleventy.js", - "test": "npx nyc --reporter=lcov ava" + "test": "npx nyc --reporter=lcov --reporter=text ava" }, + "files": [ + "src" + ], "repository": { "type": "git", "url": "git+https://github.com/artstorm/eleventy-plugin-seo.git" diff --git a/src/MetaRobots.js b/src/MetaRobots.js new file mode 100644 index 0000000..b29252c --- /dev/null +++ b/src/MetaRobots.js @@ -0,0 +1,22 @@ +const BaseTag = require("./BaseTag"); + +class MetaRobots extends BaseTag { + getObject() { + return { + render: (scope, hash) => { + const pagination = scope.contexts[0].pagination; + let robots = "index,follow"; + + if (pagination) { + if (pagination.pageNumber > 0) { + robots = `no${robots}`; + } + } + + return Promise.resolve(robots); + } + }; + } +} + +module.exports = MetaRobots; diff --git a/src/SEO.js b/src/SEO.js index 93aa8f3..6f0fa1a 100644 --- a/src/SEO.js +++ b/src/SEO.js @@ -6,6 +6,8 @@ class SEO extends BaseTag { parse: (tagToken, remainToken) => {}, render: async (scope, hash) => { const template = ` + + `; diff --git a/test/MetaRobotsTest.js b/test/MetaRobotsTest.js new file mode 100644 index 0000000..16aa6ab --- /dev/null +++ b/test/MetaRobotsTest.js @@ -0,0 +1,42 @@ +import test from "ava"; +import MetaRobots from "../src/MetaRobots"; + +test.beforeEach(t => { + t.context.scope = { + contexts: [ + { + pagination: { + pageNumber: 0 + } + } + ] + }; +}); + +test("Ordinary pages gets index and follow", t => { + const metaRobots = new MetaRobots(); + const object = metaRobots.getObject(); + + return object.render(t.context.scope).then(result => { + t.is(result, "index,follow"); + }); +}); + +test("Ordinary pages gets noindex and follow", t => { + const metaRobots = new MetaRobots(); + const object = metaRobots.getObject(); + t.context.scope.contexts[0].pagination.pageNumber = 1; + + return object.render(t.context.scope).then(result => { + t.is(result, "noindex,follow"); + }); +}); + +test("Missing pagination gets index and follow", t => { + const metaRobots = new MetaRobots(); + const object = metaRobots.getObject(); + + return object.render({ contexts: [{}] }).then(result => { + t.is(result, "index,follow"); + }); +}); diff --git a/test/SEOTest.js b/test/SEOTest.js index 3f2fd61..2796d08 100644 --- a/test/SEOTest.js +++ b/test/SEOTest.js @@ -31,6 +31,8 @@ test("SEO renders template", t => { const seo = new SEO(liquidEngine, config); const object = seo.getObject(); + object.parse(); + return object.render(t.context.scope).then(result => { t.truthy( result.includes(``)