gohugoio / hugo

The world’s fastest framework for building websites.
https://gohugo.io
Apache License 2.0
74.64k stars 7.45k forks source link

Load SVG files with esbuild's api.LoaderText with in js.Build #9978

Open zmsy opened 2 years ago

zmsy commented 2 years ago

On my site I've got a custom color theme selector, and I've got a Preact element where I'd like to inline an SVG so I can apply styles to it, and make it responsive to CSS custom properties. This is currently achieved using a custom Figure component:

// Figure.tsx

import { FunctionComponent } from "preact";

export const Figure: FunctionComponent<{ svg: string }> = ({ svg }) => {
  // This "color-responsive-svg" class adds a number of selectors for the paths, etc within the svg to
  // make them response to various css custom properties, and then the actual SVG file gets inlined
  // here as a child element.
  return (
    <figure class="color-responsive-svg" dangerouslySetInnerHTML={{ __html: svg }} />
  );
};

Below, using the component like so doesn't work. You'll get something akin to JSBUILD: failed to transform "ts/index.tsx" (text/tsx): "my-icon.svg:1:0": Unexpected "<"

// NavModal.tsx

import { Figure } from "./Figure";
import myIcon from "./my-icon.svg";

export const NavModal: FunctionComponent = () => {
  return (
    <Figure svg={myIcon} />
  );
};

If you switch the file extension to .txt, you can import the file and render it as expected. This looks like it's because ".svg" is currently not supported in the extensions array: https://github.com/gohugoio/hugo/blob/master/resources/resource_transformers/js/options.go#L134

It looks like loading SVG as text is the documented approach for using this in ESBuild, and that seems like a nice default to me.

stackkrocket commented 2 years ago

Has this been fixed?

bep commented 2 years ago

@stackkrocket the issue is open and there are no PRs referencing it == not fixed.

stackkrocket commented 2 years ago

@zmsy I found an ESBuild pluggin that adds supports for ".svg" here

stackkrocket commented 2 years ago

@bep From, Although I would love to investigate further and take a crack at this for enhancement.

bep commented 2 years ago

From what I understand @zmsy the solution to this is to add ".svg": api.LoaderText here:

https://github.com/gohugoio/hugo/blob/master/resources/resource_transformers/js/options.go#L134

Note that any JavaScript ESBuild plugins you find on the interweb is not relevant for Hugo.

stackkrocket commented 2 years ago

It is a quick fix actually. I can quickly add this.

stackkrocket commented 2 years ago

@bep I think I may have missed some few pointer in the contributing guidelines. I wish to correct them and make subsequent adequate changes that fixes this issue.

zmsy commented 2 years ago

From what I understand @zmsy the solution to this is to add ".svg": api.LoaderText here:

https://github.com/gohugoio/hugo/blob/master/resources/resource_transformers/js/options.go#L134

Note that any JavaScript ESBuild plugins you find on the interweb is not relevant for Hugo.

This seemed like the case. I haven't had the time yet to actually try building the repo with that change made and testing it, but seems like @stackkrocket is already on it 👍 Seemed like a simple update and just wanted to submit the issue first.

NOTE: For anybody reading this issue - If you're importing SVG files and you don't want Typescript to flag them with an error, you can add a .d.ts file to your top-level assets directory (same level as your tsconfig.json) with the file type defined:

declare module "*.svg" {
  const content: string;
  export default content;
}
stackkrocket commented 2 years ago

@bep Have you had time to go through my edited commit? It seems I have passed all the checks to make a successful commit/PR.