natemoo-re / astro-icon

Inline and sprite-based SVGs in Astro made easy!
https://astroicon.dev
Other
990 stars 57 forks source link

I get this error: Unable to load the "local" icon set! #209

Open stanislav-kukucka opened 4 months ago

stanislav-kukucka commented 4 months ago

What version of astro-icon are you using?

v1.0.1

Astro Info

✅ I am using the latest version of Astro Icon.
✅ Astro Icon has been added to my astro.config.mjs file as an integration.
✅ I have installed the corresponding @iconify-json/* packages.
✅ I am using the latest version of Astro and all plugins.
✅ I am using a version of Node that Astro supports (>=18.14.1)

If this issue only occurs in one browser, which browser is a problem?

all

Describe the Bug

I get this Astro error:

Unable to load the "local" icon set!
It looks like the "local" set was not loaded.
Did you forget to create the icon directory or to update your config?

and this error

// @ts-ignore virtual module
import icons, { config } from "virtual:astro-icon";
// @ts-ignore generated by typegen
import type { Icon } from "virtual:astro-icon";
import { getIconData, iconToSVG } from "@iconify/utils";
import type { HTMLAttributes } from "astro/types";
import { cache } from "./cache.js";

interface Props extends HTMLAttributes<"svg"> {
  name: Icon;
  "is:inline"?: boolean;
  title?: string;
  size?: number;
  width?: number;
  height?: number;
}

class AstroIconError extends Error {
  public hint: string;

  constructor(message: string) {
    super(message);
  }
}

const req = Astro.request;
const { name = "", title, "is:inline": inline = false, ...props } = Astro.props;
const map = cache.get(req) ?? new Map();
const i = map.get(name) ?? 0;
map.set(name, i + 1);
cache.set(req, map);

const { include = {} } = config;
const sets = Object.keys(include);

const includeSymbol = !inline && i === 0;

let [setName, iconName] = (name as string).split(":");

if (!setName && iconName) {
  const err = new AstroIconError(`Invalid "name" provided!`);
  if (import.meta.env.DEV) {
    err.hint = `The provided value of "${name}" is invalid.\n\nDid you forget the icon set name? If you were attemping to reference a local icon, use the icon's name directly. (ie. "${iconName}")`;
  }
  throw err;
}

// No iconName, assume local icon reference
if (!iconName) {
  // Assign the provided setName to the iconName
  iconName = setName;
  setName = "local";

  // Check if the local icon set exists
  if (!icons[setName]) {
    const err = new AstroIconError('Unable to load the "local" icon set!');
    if (import.meta.env.DEV) {
      err.hint =
        'It looks like the "local" set was not loaded.\n\nDid you forget to create the icon directory or to update your config?';
    }
    throw err;
  }

  // Check if the icon is missing from the local collection
  if (!(iconName in icons[setName].icons)) {
    const err = new AstroIconError(`Unable to locate "${name}" icon!`);
    if (import.meta.env.DEV) {
      err.hint = `The icon named "${iconName}" was not found in your local icon directory.\n\nDid you forget to configure your icon directory or make a typo?`;
    }
    throw err;
  }
}

const collection = icons[setName];

// Iconify collection not configured correctly
if (!collection) {
  const err = new AstroIconError(`Unable to locate the "${setName}" icon set!`);
  if (import.meta.env.DEV) {
    if (sets.includes(setName)) {
      err.hint = `It looks like the "${setName}" set was not loaded.\n\nDid you install the "@iconify-json/${setName}" dependency?`;
    } else {
      err.hint = `It looks like the "${setName}" set is not included in your configuration.\n\nDo you need to add the "${setName}" set?`;
    }
  }
  throw err;
}

const iconData = getIconData(collection, iconName ?? setName);
// Missing icon from the icon collection
if (!iconData) {
  const err = new AstroIconError(`Unable to locate "${name}" icon!`);
  if (import.meta.env.DEV) {
    const [maybeStar] = include[setName];
    if (maybeStar === "*" || include[setName].includes(iconName)) {
      err.hint = `The "${setName}" set does not include an icon named "${iconName}".\n\nIs this a typo?`;
    } else {
      err.hint = `The "${setName}" set is not configured to include an icon named "${iconName}".\n\nDo you need to add it to your configuration?`;
    }
  }
  throw err;
}

const id = `ai:${collection.prefix}:${iconName ?? setName}`;

if (props.size) {
  props.width = props.size;
  props.height = props.size;
  delete props.size;
}
const renderData = iconToSVG(iconData);
const normalizedProps = { ...renderData.attributes, ...props };
const normalizedBody = renderData.body;
---

<svg {...normalizedProps} data-icon={name}>
  {title && <title>{title}</title>}
  {
    inline ? (
      <Fragment id={id} set:html={normalizedBody} />
    ) : (
      <Fragment>
        {includeSymbol && <symbol id={id} set:html={normalizedBody} />}
        <use xlink:href={`#${id}`} />
      </Fragment>
    )
  }
</svg>

What's the expected result?

to be able to work with your library on my project

Link to Minimal Reproducible Example

test

linyiru commented 3 months ago

@stanislav-kukucka Not sure if you've sorted it out later? I encountered the same error message as you, and later found out that I passed an incorrect string when displaying the icon. This string was dynamically generated by a function, so I didn't realize it immediately.