Automattic / node-canvas

Node canvas is a Cairo backed Canvas implementation for NodeJS.
10.09k stars 1.16k forks source link

Text with .woff font generating as unicode code boxes instead of text in Netlify build only #1966

Open qxorio opened 2 years ago

qxorio commented 2 years ago

Issue

I have node-canvas installed on an eleventy website that is being used to generate OpenGraph images and stored in an image CDN. I'm running MacOS locally with npm 8.1.2, node 16.13.1, and canvas 2.8.0. I am using some .woff fonts available in my project to help generate the OG images. When building the project locally, everything works fine and I see my expected image uploaded to my image CDN.

When deploying to Netlify (running same node and npm versions) I get an image uploaded to my image CDN but it shows box characters with corresponding character unicode values inside. No exceptions, warnings, or errors in the build log of Netlift. I'm a bit confused where to even begin looking, so help is appreciated!

OpenGraph image with unicode character boxes with instead of text

You can see the file using canvas in the repository here. I will include the entirety of the file below.

Steps to Reproduce

You can attempt to clone the repository, but it expects some environment variables for Notion and Cloudinary. The real issue is uploading to Netlify.

const { createCanvas, registerFont } = require("canvas");
var slugify = require("slugify");
const cloudinary = require("./utils").cloudinary;

const width = 1200;
const height = 630;

async function generate(post) {
    registerFont("./src/assets/fonts/viaoda-libre/viaoda-libre.woff", { family: "Viaoda Libre" });
    registerFont("./src/assets/fonts/firasans-light/firasans-light.woff", { family: "Fira Sans" });

    const canvas = createCanvas(width, height);
    const context = canvas.getContext("2d");

    context.textAlign = "center";

    context.fillStyle = "#ececec";
    context.fillRect(0, 0, width, height);

    // Add titles
    context.fillStyle = "#3c5237";
    context.font = "60pt Viaoda Libre";
    context.fillText("quinn tenorio", canvas.width / 2, 100);

    context.fillStyle = "#000";
    context.font = "85pt Viaoda Libre";
    context.fillText(`${post.title}`, canvas.width / 2, canvas.height / 2 + 40);

    // Add labels
    context.font = "35pt Fira Sans";
    context.fillText(`${post.published} • ${post.tags.join(", ")}`, canvas.width / 2, 575);

    const base64 = canvas.toDataURL("image/jpeg");

    let file = "posts/" + slugify(post.title, { lower: true }) + "/" + slugify(post.title, { lower: true });
    let response = await cloudinary.uploader.upload(
        base64,
        {
            public_id: file,
        },
        function (err, res) {
            if (err) console.warn(err);
            return res.secure_url;
        }
    );

    return response.secure_url;
}

exports.generateOgImage = generate;

Netlify build log:

4:26:26 PM: ──────────────── 4:26:26 PM: 1. build.command from netlify.toml
4:26:26 PM: ──────────────── 4:26:26 PM: ​ 4:26:26 PM: $ npm run build 4:26:27 PM: > quinn-website@1.0.0 build 4:26:27 PM: > npm run sass && eleventy 4:26:27 PM: > quinn-website@1.0.0 sass 4:26:27 PM: > sass --no-source-map --style compressed src/assets/styles/main.scss _site/assets/styles/main.min.css 4:26:31 PM: Writing _site/404.html from ./src/404.njk. 4:26:31 PM: Writing _site/bookshelf/index.html from ./src/bookshelf.njk. 4:26:31 PM: Writing _site/index.html from ./src/index.njk. 4:26:31 PM: Writing _site/posts/a-fresh-start/index.html from ./src/post.njk. 4:26:31 PM: Writing _site/posts/index.html from ./src/posts.njk. 4:26:31 PM: Writing _site/bookshelf/when-breath-becomes-air/index.html from ./src/book.njk. 4:26:31 PM: Writing _site/bookshelf/educated/index.html from ./src/book.njk. 4:26:31 PM: Writing _site/bookshelf/crying-in-h-mart/index.html from ./src/book.njk. 4:26:31 PM: Writing _site/bookshelf/ready-player-one/index.html from ./src/book.njk. 4:26:31 PM: Creating deploy upload records 4:26:31 PM: Writing _site/bookshelf/dark-matter/index.html from ./src/book.njk. 4:26:31 PM: Writing _site/bookshelf/dune/index.html from ./src/book.njk. 4:26:31 PM: Benchmark (Data): ./src/_data/books.js took 727ms (24.1%) 4:26:31 PM: Benchmark (Data): ./src/_data/posts.js took 1984ms (65.8%) 4:26:31 PM: Copied 15 files / Wrote 11 files in 2.93 seconds (266.4ms each, v0.12.1) 4:26:31 PM: ​ 4:26:31 PM: (build.command completed in 4.6s)

Your Environment

jamesjoung commented 1 year ago

Happening same for me. It worked fine on node 14 with canvas 2.6.1 and anything above, all woff files are showing box with unicode. However ttf file works fine.

What are the changes between 2.6.1 vs +?

And also, node 16 and node 18 also breaks on 2.6.1.

Seems like either upgrading node OR canvas package breaks the font.

jamesjoung commented 1 year ago

Very much related to https://github.com/Automattic/node-canvas/issues/1737.

Long story short, woff support has been broken on any version above 2.6.1+

Currently Node 14 with Canvas 2.6.1 works with woff