Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
hexo-covers
Advanced tools
hexo-covers
is a plugin for Hexo static site generator that generates microbrowser page cover so you'll have compelling webpage preview while sharing the link via iMessage, WhatsApp, Telegram, Facebook and others.
As more of our conversations happen in group chats and slack channels, link previews are an important way for you to engage users before they start the journey on your site. To help users take the leap and visit your site, we need to make sure that all our pages are annotated with microdata. Better yet, we can use these previews to create compelling visual summaries.
— Colin Bendell • Microbrowsers are Everywhere
hexo-covers
runs Chromium via puppeteer and takes the screenshot.resolve_cover
, resolve_tag_cover
, resolve_category_cover
helpers. For more information see below.hexo-covers
runs Chromium via puppeteer for every cover and takes the screenshot./.covers/
) and included in the cache manifest (/.covers/covers.json
). You should not care about the folder structure in this folder. Ensure that .covers
folder added to your repo. If it's ignored, cover processing will start each time, which is time-consuming.hexo-covers
generated the covers, you'll need to specify special meta tags so microbrowsers could discover it (for more information see below).The crucial part of the adding previews is page metadata. You can find more information about it here and here. In general, you'll need to add few tags into the <head>
section:
<html>
<head>
...
<meta property="og:title" content="Website title" />
<meta name="twitter:title" content="Website title />
<link rel="image_src" href="< link to your image preview >" />
<meta name="twitter:image:src" content="< link to your image preview >" />
<meta property="og:image" content="< link to your image preview >" />
</head>
<body>
...
</body>
</html>
In addition, you can add a few more tags like og:type
, og:description
, og:image:type
, og:image:width
, og:image:height
, article:author
, twitter:description
, twitter:site
, twitter:card
and others, but it's completely up to you.
To add this, you'll need to modify layout.ejs
template in your theme folder. I personally prefer to determine layout type and render some partial there. This is how <head>
section of the layout.ejs
template could look:
<head>
...
<%_ let layout = page.layout;
if (!layout) {
if (page.tag) {
layout = 'tag';
} else if (page.category) {
layout = 'category';
}
} _%>
<%_ if (layout) { _%>
<%- partial(`_partial/microbrowsers/${layout}`) %>
<%_ } _%>
</head>
Adding this snippet triggers partial render for every type of layout, e.g. _partial/microbrowsers/page.ejs
will be generated for page
layout, _partial/microbrowsers/post.ejs
will be generated for post
layout, etc.
Here are a few examples of how to define these partials:
resolve_cover
tag helper is used to retrieve information about the cover image.
<%_ const cover = resolve_cover() _%>
<meta property="og:type" content="article" />
<meta property="og:url" content="<%= page.permalink %>" />
<meta property="og:title" content="<%= page.title %>" />
<meta property="og:description" content="<%= page.description %>" />
<%_ if (cover) { _%>
<link rel="image_src" href="<%= full_url_for(cover.file) %>" />
<meta property="og:image" content="<%= full_url_for(cover.file) %>" />
<meta property="og:image:type" content="image/<%= cover.type %>" />
<meta property="og:image:width" content="<%= cover.dimensions.w %>" />
<meta property="og:image:height" content="<%= cover.dimensions.h %>" />
<%_ } _%>
<meta name="twitter:title" content="<%= page.title %>" />
<meta name="twitter:description" content="<%= page.description %>" />
<meta property="twitter:url" content="<%= page.permalink %>" />
<meta name="twitter:card" content="summary_large_image" />
<%_ if (cover) { _%>
<meta name="twitter:image:src" content="<%= full_url_for(cover.file) %>" />
<%_ } _%>
resolve_tag_cover
tag helper should be used instead of ``resolve_cover`.
<%_ const cover = resolve_tag_cover(page.tag) _%>
<meta property="og:type" content="article" />
<meta property="og:title" content="<%= page.tag %>" />
<%_ if (cover) { _%>
<link rel="image_src" href="<%= full_url_for(cover.file) %>" />
<meta property="og:image" content="<%= full_url_for(cover.file) %>" />
<meta property="og:image:type" content="image/<%= cover.type %>" />
<meta property="og:image:width" content="<%= cover.dimensions.w %>" />
<meta property="og:image:height" content="<%= cover.dimensions.h %>" />
<%_ } _%>
<meta name="twitter:title" content="<%= page.tag %>" />
<meta name="twitter:card" content="summary_large_image" />
<%_ if (cover) { _%>
<meta name="twitter:image:src" content="<%= full_url_for(cover.file) %>" />
<%_ } _%>
resolve_category_cover
tag helper should be used instead of ``resolve_cover`.
<%_ const cover = resolve_category_cover(page.category) _%>
<meta property="og:type" content="article" />
<meta property="og:title" content="<%= page.category %>" />
<%_ if (cover) { _%>
<link rel="image_src" href="<%= full_url_for(cover.file) %>" />
<meta property="og:image" content="<%= full_url_for(cover.file) %>" />
<meta property="og:image:type" content="image/<%= cover.type %>" />
<meta property="og:image:width" content="<%= cover.dimensions.w %>" />
<meta property="og:image:height" content="<%= cover.dimensions.h %>" />
<%_ } _%>
<meta name="twitter:title" content="<%= page.category %>" />
<meta name="twitter:card" content="summary_large_image" />
<%_ if (cover) { _%>
<meta name="twitter:image:src" content="<%= full_url_for(cover.file) %>" />
<%_ } _%>
You can specify custom data for every page that will be passed in the template during the build. To do that add the cover
key in page/post frontmatter:
---
title: Test post
cover:
title: My test post
image: wp3060116.jpg
hide_logo: false
hide_title: false
hide_subtitle: false
disable_fade: false
raw: false
---
Post text
There are few predefined key that you can pass in frontmatter:
title
— overrides title of the post in the coverimage
— custom background image for the coverhide_logo
— hides blog logohide_title
— hides post titlehide_subtitle
— hides post sub-titledisable_fade
— disables background fadingraw
— do not process the cover with standard workflow, just copy image
insteadYou can use these params if you use the default template. You can also specify your own keys - all of them will be passed into the template as a query string params. It's useful when you build a custom template and want to show more data.
By default covers for tags and categories generated with name that passed from the URL (e.g. for /tag/aspnet
the name will be aspnet
). If you want to display a friendly name for tags and categories, you can specify it in an additional data file.
To do that add special configuration key source.categories.data
and source.tags.data
and specify a relative path to the data files (find more information in Configuration
section below).
Here is an example of how you can define the data file:
aspnet:
title: ASP.NET
background: aspnet.webp
frontend:
title: Frontend Development
background: frontend.webp
In addition, you can specify background images and other custom keys that will be passed in the template file during the build via query string parameters. Also, you'll need to specify source.categories.images
and source.tags.images
parameters in configuration to be able to override cover background via data file.
The template is a regular HTML file. During the cover build hexo-covers
starts web-server that serves the template. After that puppeteer is used to take a screenshot of the page.
There is a default template that looks like this way:
If you are OK with the style of the default template, you do not need to do anything about it. If you want to customize the look of the cover, read the next section.
If you want to customize the look of the cover, feel free to create an HTML file somewhere in the project folder. To let hexo-covers
know where is your template located, specify the relative path in the templates
section of configuration (see below). Optionally, you can define additional images that will be passed into the template. All paths are relative, so you can use any images from your project you want.
Use the default template as a reference on how to create your own template. Pay attention to JavaScript code in the default template. There is a code to extract params from the query string (which passed by hexo-covers
) as well as the code that throws an error when title text is too large to render.
Any JavaScript error that throws on the template page will generate error in Hexo console during the build. It introduced intentionally to avoid generating "broken" covers.
To configure the plugin add covers
key to the Hexo config file. For example:
covers:
enable: true
title: 'Your blog title'
base_dir: '.covers'
manifestFileName: 'covers.json'
include:
- keywords
tagsUrl: tag
categoriesUrl: category
compress: true
source:
categories:
data: _data/categories.yml
images: _covers/categories
tags:
data: _data/tags.yml
images: _covers/tags
templates:
page:
path: themes/theme1/layout/microbrowser-template/page.html
images:
logo: themes/theme1/source/assets/favicon/favicon-194x194.png
background: themes/theme1/layout/microbrowser-template/bg.svg
dimensions:
width: 964
height: 504
post:
path: themes/theme1/layout/microbrowser-template/post.html
images:
logo: themes/theme1/source/assets/favicon/favicon-194x194.png
background: themes/theme1/layout/microbrowser-template/bg.svg
dimensions:
width: 964
height: 504
category:
path: themes/theme1/layout/microbrowser-template/category.html
images:
logo: themes/theme1/source/assets/favicon/favicon-194x194.png
background: themes/theme1/layout/microbrowser-template/bg.svg
dimensions:
width: 964
height: 504
tag:
path: themes/theme1/layout/microbrowser-template/tag.html
images:
logo: themes/theme1/source/assets/favicon/favicon-194x194.png
background: themes/theme1/layout/microbrowser-template/bg.svg
dimensions:
width: 964
height: 504
Key | Required | Default value | Description |
---|---|---|---|
enable | false | true | Flag to disable plugin execution. |
title | false | Your website title in Hexo configuration | The website title value that will be passed into the template. |
base_dir | false | .images | Directory name to store cover cache. |
manifestFileName | false | images.json | File name to store cover cache manifest (for more info see below). |
include | false | [ keywords ] | Frontmatter keys that will be available at the template during preview generating. |
tagsUrl | false | tag | The URL where tag covers will be produced. |
categoriesUrl | false | tag | The URL where category covers will be produced. |
compress | false | true | Determines if output cover images will be compressed. |
source.categories.data | false | _data/categories.yml | Path to yaml file that provides additional data for categories (for more information see above). |
source.categories.images | false | _covers/categories | Path to images folder for categories (for more information see above). |
source.tags.data | false | _data/tags.yml | Path to yaml file that provides additional data for tags (for more information see above). |
source.tags.images | false | _covers/tags | Path to images folder for tags (for more information see above). |
templates | false | Definition of templates for pages, posts, tags, and categories. | |
templates.page.path templates.post.path templates.category.path templates.tag.path | true | Path to default template | Relative path to template file. |
templates.page.images templates.post.images templates.category.images templates.tag.images | false | { background: "lib/templates/bg.svg" } | Images that will be passed into template during generating. |
templates.page.dimensions templates.post.dimensions templates.category.dimensions templates.tag.dimensions | true | { width: 964, height: 504 } | Size of generated cover image for the template. |
Normally, you shouldn't care about the manifest structure. But if you're curious, the manifest is a JSON file that contains key-value collection of processed files. The key is a relative path to the image. The value is information about the processed cover. All items are grouped into sections — tags
, categories
, pages
, posts
.
Here is an example:
{
"tags": {
"dotnet": {
"file": "tags/8ec70aeb/dotnet@cover.jpg",
"size": 17476,
"hash": "8ec70aebbc51e28b158a13af745f1bb3",
"type": "jpg",
"dimensions": {
"w": 964,
"h": 504
}
}
},
"categories": {
"mobile": {
"file": "categories/95306cf2/mobile@cover.jpg",
"size": 28816,
"hash": "95306cf2703054c1fe91c432f82a8721",
"type": "jpg",
"dimensions": {
"w": 964,
"h": 504
}
}
},
"pages": {
"terms/index.md": {
"file": "pages/83c8a774/index@cover.jpg",
"size": 34955,
"hash": "83c8a77498a457a187a007c7f4a408c7",
"type": "jpg",
"dimensions": {
"w": 964,
"h": 504
}
}
},
"posts": {
"_posts/2014/fronttalks-2014.md": {
"file": "posts/2c7f8a02/fronttalks_2014@cover.jpg",
"size": 29735,
"hash": "2c7f8a02c9c676e12487c0fc64e65c4f",
"type": "jpg",
"dimensions": {
"w": 964,
"h": 504
}
}
}
}
In page template you can also access cover
property that will contain the part of the manifest that related to the current page.
FAQs
Microbrowsers cover generator for Hexo static site generator
The npm package hexo-covers receives a total of 6 weekly downloads. As such, hexo-covers popularity was classified as not popular.
We found that hexo-covers demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer 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.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.