Preface
Hexo blogs display web pages by rendering Markdown files into HTML files, which means that a standalone PDF file cannot be easily displayed on a Hexo blog. This article introduces three methods for directly displaying PDF files, discussing the advantages and disadvantages of each. You can choose the PDF display method according to your specific needs.
Using the hexo-pdf Plugin
The hexo-pdf plugin is a Hexo blog plugin that allows us to directly insert PDF files into Markdown documents.
Installing the hexo-pdf Plugin
$ npm install --save hexo-pdf
Usage
After installation is complete, insert the following code at an appropriate location in your Markdown file:
{% pdf <url-to-pdf> %}
Here, <url-to-pdf> can be either a URL or a local path pointing to the PDF file you want to display.
Advantages and Disadvantages
The advantage of this method is that PDFs can be inserted very conveniently. However, it only displays on desktop devices; on mobile devices, it will appear transparent and fail to display. If you don’t need to accommodate mobile access, this issue can be ignored. Alternatively, you can export the PDF as images and place them below for mobile users to access.
Using the <iframe> Tag
Markdown and HTML are closely related, and HTML syntax is fully compatible within Markdown. Most browsers also support the <iframe> tag, so it can be used to implement PDF preview functionality.
Usage
Insert the following code at an appropriate location in your Markdown file:
<iframe src="/index.pdf" width="100%" height="100%"></iframe>
Place the URL or path of the PDF file in the quotes of the src attribute. The width and height parameters define the size of the PDF preview window and can be adjusted according to your needs. It is recommended to keep width at 100% and choose a height value between 500px and 900px to balance the preview experience between desktop and mobile devices.
Advantages and Disadvantages
Unfortunately, mobile devices can only display the first page of the PDF, while desktop devices display normally with a complete PDF preview component.
If you want to consider the mobile user experience, in addition to adding image previews, you can use HTML syntax to add a download link (provided you have a direct URL to the file). The complete code is as follows:
<iframe src="/index.pdf" width="100%" height="100%">
This browser does not support PDFs. Please download the PDF to view it: <a href="/index.pdf">Download PDF</a>
</iframe>
The src attribute is the same as above. Place the direct link to the PDF file in the href attribute.
The Perfect Ultimate Solution — pdf.js
Introduction: Let’s Learn About This Remarkable Project
PDF.js is a Portable Document Format (PDF) viewer built using HTML5.
pdf.js is community-driven and supported by Mozilla. Its goal is to create a general-purpose, web standards-based platform for parsing and rendering PDFs.
Download and Usage
Download, Extract, and Upload
The files can be downloaded from the official pdf.js GitHub repository: https://github.com/mozilla/pdf.js. You can download your preferred version; I am using the older version 3.4 here.
After downloading, extract and upload it to the /root/blog/themes/butterfly/source/js folder on your server, where “blog” is the root directory of your Hexo blog. If your theme is not Butterfly, please replace “butterfly” with your theme name, and rename the folder to “pdfjs” (to ensure you can use the code below directly).
Modify the viewer.js File to Prevent Cross-Origin Errors
Locate the viewer.js file in the /root/blog/themes/butterfly/source/js/pdfjs/web directory (adjust the directory as mentioned above). Make the changes shown in the image by commenting out the indicated code.
Avoid Rendering
If pdfjs is in the source folder, it may be rendered as documents by Hexo. You need to tell Hexo not to render folders intended to be used as libraries.
In the Hexo configuration file _config.yml, under the skip_render entry, add the pdfjs folder path relative to source:
skip_render:
- js/**
Usage (PDF File Located Locally)
In your Markdown document, use the <iframe> control in conjunction with the pdf.js library to display PDFs:
<iframe src='/js/pdfjs/web/viewer.html?file=<src-to-pdf>' style='width:100%;height:100%'></iframe>
The first part of the src is the directory of viewer.html relative to the source folder. If you followed the previous steps exactly as I did, you don’t need to modify it. The <src-to-pdf> portion is the path of the PDF file relative to the source folder. The style attribute sets the width and height, which can be configured entirely according to your preferences.
What if it’s a URL? Good question. If, like me, you store PDF files in your own Cloudreve cloud storage, you will encounter a series of errors. Different browsers display different error messages, but they generally relate to CORS (Cross-Origin Resource Sharing) issues—cross-origin access being denied. Below, I’ll explain how to implement CORS to insert PDFs using URLs. (PS: If you obtain a direct link to a PDF file through other means, I don’t know if you’ll encounter the same errors as I did.)
Using URLs to Preview PDFs
First, you need to set <src-to-pdf> to the direct URL of your PDF file. At this point, performing the standard Hexo three-step deployment won’t work because, due to cross-origin restrictions, pdf.js cannot access the PDF file from the URL, so neither desktop nor mobile devices can display it. You need to add headers to allow cross-origin access.
Go to Cloudflare and host your domain on Cloudflare (if you’ve already done this, please skip this step).
Enter your domain, select Rules, add a Transform Rule for response headers, and complete the following configuration:
Set the value of Access-Control-Allow-Origin to your blog’s domain (including https:// or http://). After saving, wait a moment and refresh the page—you’re all done!
At this point, you’ll find that both desktop and mobile devices can now access it!
Mission accomplished! ✿✿ヽ(°▽°)ノ✿
Unfortunately, it’s not actually finished yet. Most of the time everything works normally, but on February 26, 2025, when I uploaded an 8+ MB PDF, it wouldn’t display on desktop at all. After checking the error, it indicated that the PDF format was not supported. I searched extensively but found no solution, and it was suggested that upgrading the version would fix it. However, the reason I originally chose version 3.x instead of 4.x was because 4.x uses the mjs format, which caused errors when used directly. But I stubbornly changed the script anyway, and while the desktop could now display PDFs, mobile devices couldn’t. Testing revealed it simply wouldn’t display, though downloading through that page was still possible. Well, let’s assume it’s a version issue. So below, I’ll discuss using version 4.x.
To resolve the mjs issue, we need to access the server that the domain points to and add the following code to the Nginx configuration file:
http {
include mime.types;
types {
application/javascript js mjs;
}
default_type application/octet-stream;
Then change the reference format in the md file to: <iframe src="domain/pdfjs/web/viewer.html?file=/(PDF-folder)/(PDF-filename).pdf" width="100%" height="500px" frameborder="0"></iframe>. This assumes the pdfjs folder is located in the [Blogroot]/source folder and the folder is named “pdfjs”. If yours differs, please remember to make changes accordingly. Also remember to add the pdfjs folder to skip_render, otherwise this folder will be rendered as well. Then perform the Hexo three-step deployment and you’re done! Both desktop and mobile devices work normally!
By the way, I’ve seen people online suggest simply changing the mjs extension to js, which, although I haven’t tried it, seems unreliable. Feel free to try it yourself if you’re interested.
Mission accomplished! ✿✿ヽ(°▽°)ノ✿ (Finally, truly mission accomplished)