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

Add image meta tags to De-risking Guide pages #713

Merged
merged 4 commits into from
Sep 24, 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
7 changes: 6 additions & 1 deletion .eleventy.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const svgSprite = require("eleventy-plugin-svg-sprite");
const syntaxHighlight = require("@11ty/eleventy-plugin-syntaxhighlight");
const yaml = require("js-yaml");

const { imageShortcode, imageWithClassShortcode } = require('./config');
const { imageShortcode, imageWithClassShortcode, imageUrl } = require('./config');

const siteData = yaml.load(fs.readFileSync('./_data/site.yaml', 'utf8'));

Expand Down Expand Up @@ -98,6 +98,11 @@ module.exports = function (config) {
return value.charAt(0).toUpperCase() + value.slice(1);
});

// Get the URL for an image given the relative path to its source
config.addFilter('imageUrl', (imageSource) => {
return imageUrl(imageSource);
});

// Create an array of all tags
config.addCollection('tagList', function (collection) {
let tagSet = new Set();
Expand Down
3 changes: 3 additions & 0 deletions _data/meta_images.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Optional meta image tag information for each guide
derisking-government-tech:
path: assets/derisking-government-tech/img/icon.jpg
13 changes: 13 additions & 0 deletions _includes/meta.html
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,19 @@
<meta name="description" content="{{description}}" />
<meta property="og:description" content="{{description}}" />

{% comment %}
Meta image and alt text, if specified. og:image requires an absolute URL. Outside of production,
the environment config doesn't include the domain, so use a relative path for testing purposes.
{% endcomment %}
{% if meta_images[guide] and meta_images[guide].path %}
{% assign meta_image_url = meta_images[guide].path | imageUrl %}
{% if env.production %}
{% assign meta_image_url = meta_image_url | asAbsoluteUrl %}
{% endif %}
<meta property="og:image" content="{{ meta_image_url }}" />
<meta property="og:image:alt" content="{{ meta_images[guide].alt }}" />
{% endif %}

<meta name="twitter:card" content="summary" />
<meta name="twitter:site" content="@{{site.twitter}}" />
<meta name="twitter:description" content="{{description}}" />
Expand Down
Binary file added assets/derisking-government-tech/img/icon.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
15 changes: 15 additions & 0 deletions assets/derisking-government-tech/img/software-solution.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
39 changes: 27 additions & 12 deletions config/index.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,7 @@
const path = require('path');
const Image = require('@11ty/eleventy-img');

async function imageWithClassShortcode(
src,
cls,
alt,
) {
let pathPrefix = '';

if (process.env.BASEURL) {
pathPrefix = process.env.BASEURL;
}

async function imageData(src) {
const ext = path.extname(src);
const fileType = ext.replace('.', '');

Expand All @@ -21,7 +11,31 @@ async function imageWithClassShortcode(
});

const data = metadata[fileType] ? metadata[fileType][0] : metadata.jpeg[0];
return `<img src="${pathPrefix}${data.url}" class="${cls}" alt="${alt}" loading="lazy" decoding="async">`;
return data;
}

function getPathPrefix() {
let pathPrefix = '';

if (process.env.BASEURL) {
pathPrefix = process.env.BASEURL;
}
return pathPrefix;
}

async function imageUrl(src) {
const pathPrefix = getPathPrefix();
const data = await imageData(src);
return `${pathPrefix}${data.url}`;
}

async function imageWithClassShortcode(
src,
cls,
alt,
) {
const url = await imageUrl(src);
return `<img src="${url}" class="${cls}" alt="${alt}" loading="lazy" decoding="async">`;
}

async function imageShortcode(src, alt) {
Expand All @@ -31,4 +45,5 @@ async function imageShortcode(src, alt) {
module.exports = {
imageWithClassShortcode,
imageShortcode,
imageUrl,
};
2 changes: 1 addition & 1 deletion content/derisking-government-tech/home/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ This guide was written to give government tools to lower the high risk of failur
<div class="usa-card__container">
<div class="usa-card__media">
<div class="usa-card__img bg-primary-darker flex-align-center flex-justify-center height-card-lg">
{%- image_with_class "assets/derisking-government-tech/img/software-solution.png" "" -%}
{%- image_with_class "assets/derisking-government-tech/img/software-solution.svg" "" -%}
</div>
</div>
<div class="usa-card__body">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ subnav:

<p class="chapter-summary">Understanding the benefits and risks of commercially available off-the-shelf (COTS) and custom software will help government agencies choose a solution appropriate to their needs.</p>

{% include 'derisking-government-tech/chapter_image.html' img_path: "assets/derisking-government-tech/img/software-solution.png" %}
{% include 'derisking-government-tech/chapter_image.html' img_path: "assets/derisking-government-tech/img/software-solution.svg" %}

A major reason that government technology projects fail or struggle is that government agencies often approach obtaining software as a matter of building *or* buying it. The reality is more complex.

Expand Down
32 changes: 32 additions & 0 deletions docs/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,38 @@ redirect_from:
| timeRequired | short description of how much time is required for method activity | text | methods |
| category | a method's category name; do not capitalize | text | methods |

## Meta tags

Pages define metadata via HTML `meta` tags implemented in the [_includes/meta.html](https://github.com/18F/guides/blob/main/_includes/meta.html) file. A subset of tags that are defined based on the page configuration are documented below.

### OpenGraph meta tags

#### Page data

| property | content |
|---|---|
| `og:description` | The description set in the page's [front matter](#top-level). |
| `og:title` | "[\<page title\>](#page-titles) \| 18F \<guide title\>" |
| `og:type` | "article" |
| `og:url` | The page URL. |

#### Image tags

OpenGraph image tags can be configured optionally at a guide level in the [_data/meta_images.yaml](https://github.com/18F/guides/blob/main/_data/meta_images.html) file. If no configuration exists for a guide, by default no `og:image` or `og:image:alt` tags will be rendered.

| property | content |
|---|---|
| `og:image` | The URL of the image at the configured asset path set in the `path` value for the guide, if any. |
| `og:image:alt` | The alt text set in the `alt` value for the guide, or "" if `alt` is unspecified. |

### Twitter meta tags

| name | content |
|---|---|
| `twitter:card` | "summary" |
| `twitter:description` | The description set in the page's [front matter](#top-level). |
| `twitter:site` | The Twitter handle configured in the [_data/site.yaml](https://github.com/18F/guides/blob/main/_data/site.yaml) file. |

## Managing dependencies

This project uses Github's Dependabot to keep the NPM dependencies up to date.
Expand Down
Loading