Skip to content

Custom SVG's and viewBox #175

Description

@LeviSnoot

In the docs, it is mentioned that:

The file must be a plain text SVG without the SVG tag itself.

I was racking my brain for a while as to why my custom icon wasn't showing up, and it turns out that the SVG I pasted in was larger than the hardcoded 32x32px value that the custom icon handler prepends:

if (svgFileExists) {
const svgContent = await plugin.app.vault.adapter.read(svgFilePath);
const base64SVG = `data:image/svg+xml;base64,${btoa(`<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32">${svgContent}</svg>`)}`;
Icons[lang.displayName] = svgContent;
BLOBS[lang.displayName.replace(/\s/g, "_")] = `${base64SVG}`;
}

So this means that my option is to manually resize the path value for each icon I want to use so it fits in a 32x32px square. This quickly becomes tedious. Instead, I tried just throwing in my svg with the svg tag anyway:

Prettified for readability, originally one-liner

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
  <path fill="#fff" d="M11.094.47c-.842 0-1.696.092-2.552.288a11.4 11.4 0 0 0-4.87 2.423a10.6 10.6 0 0 0-2.36 2.826A10 10 0 0 0 .305 8.582c-.398 1.62-.4 3.336-.043 5.048c.085.405.183.809.31 1.212a11.9 11.9 0 0 0 1.662 3.729a3 3 0 0 0-.086.427a3.323 3.323 0 0 0 2.848 3.71a3.3 3.3 0 0 0 1.947-.346c1.045.51 2.17.864 3.339 1.04a11.7 11.7 0 0 0 4.285-.155a11.6 11.6 0 0 0 4.936-2.485a10.6 10.6 0 0 0 2.352-2.894a11.2 11.2 0 0 0 1.356-4.424a11.2 11.2 0 0 0-.498-4.335q.263-.116.486-.293h.001c.402-.322.693-.794.777-1.342a2.146 2.146 0 0 0-1.79-2.434a2.1 2.1 0 0 0-1.205.171q-.059-.064-.113-.13a11.7 11.7 0 0 0-3.476-2.93a13 13 0 0 0-1.76-.81a13.6 13.6 0 0 0-2.06-.613a12 12 0 0 0-2.48-.258Zm.714.328a10 10 0 0 1 1.028.042a9.9 9.9 0 0 1 2.743.639c.984.39 1.89.958 2.707 1.632a10.8 10.8 0 0 1 2.091 2.328q.038.06.07.12a2.12 2.12 0 0 0-.435 2.646c-.158.114-.97.692-1.634 1.183c-.414.308-.733.557-.733.557l.581.68s.296-.276.665-.638c.572-.562 1.229-1.233 1.395-1.403a2.12 2.12 0 0 0 1.907.677a11.2 11.2 0 0 1-.013 4.046a11.4 11.4 0 0 1-1.475 3.897a12.3 12.3 0 0 1-2.079 2.587c-1.19 1.125-2.633 2.022-4.306 2.531a10.8 10.8 0 0 1-3.973.484a11 11 0 0 1-3.057-.652a3.3 3.3 0 0 0 1.417-2.294a3.3 3.3 0 0 0-.294-1.842c.18-.162.403-.363.656-.6c1.015-.955 2.353-2.303 2.353-2.303l-.47-.599s-1.63.972-2.801 1.728c-.307.198-.573.378-.777.517a3.3 3.3 0 0 0-1.516-.611a3.33 3.33 0 0 0-3.487 2.017a10 10 0 0 1-.695-1.078A11 11 0 0 1 .728 14.8a10 10 0 0 1-.2-1.212c-.164-1.653.103-3.258.629-4.754a13 13 0 0 1 1.087-2.288c.57-.968 1.248-1.872 2.069-2.656A11 11 0 0 1 11.808.797Zm-.147 3.257a3.84 3.84 0 0 0-3.82 3.82v2.36h-.94c-.751 0-1.377.625-1.377 1.377v3.8h1.46v-3.718h9.354v6.264H10.02v1.46h6.4c.751 0 1.377-.625 1.377-1.377v-6.43a1.39 1.39 0 0 0-1.377-1.377h-.94v-2.36a3.84 3.84 0 0 0-3.82-3.819zm0 1.46a2.37 2.37 0 0 1 2.36 2.36v2.36H9.3v-2.36a2.37 2.37 0 0 1 2.36-2.36zm10.141.392a1.253 1.253 0 0 1 1.296 1.434a1.24 1.24 0 0 1-.453.78c-.266.213-.61.318-.968.264a1.253 1.253 0 0 1-1.045-1.42a1.255 1.255 0 0 1 1.17-1.058M5.384 17.425a2.02 2.02 0 0 1 1.917 1.298c.116.3.159.628.114.967a2.015 2.015 0 0 1-2.249 1.728a2.016 2.016 0 0 1-1.727-2.25a2.02 2.02 0 0 1 1.945-1.743" />
</svg>

1

Ironically, this works. It just nests everything in the svg tag that the plugin already creates. Here's what the bundled SVG looks like after being Base64-decoded:

Prettified for readability, originally one-liner

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32">
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
    <path fill="#fff" d="M11.094.47c-.842 0-1.696.092-2.552.288a11.4 11.4 0 0 0-4.87 2.423a10.6 10.6 0 0 0-2.36 2.826A10 10 0 0 0 .305 8.582c-.398 1.62-.4 3.336-.043 5.048c.085.405.183.809.31 1.212a11.9 11.9 0 0 0 1.662 3.729a3 3 0 0 0-.086.427a3.323 3.323 0 0 0 2.848 3.71a3.3 3.3 0 0 0 1.947-.346c1.045.51 2.17.864 3.339 1.04a11.7 11.7 0 0 0 4.285-.155a11.6 11.6 0 0 0 4.936-2.485a10.6 10.6 0 0 0 2.352-2.894a11.2 11.2 0 0 0 1.356-4.424a11.2 11.2 0 0 0-.498-4.335q.263-.116.486-.293h.001c.402-.322.693-.794.777-1.342a2.146 2.146 0 0 0-1.79-2.434a2.1 2.1 0 0 0-1.205.171q-.059-.064-.113-.13a11.7 11.7 0 0 0-3.476-2.93a13 13 0 0 0-1.76-.81a13.6 13.6 0 0 0-2.06-.613a12 12 0 0 0-2.48-.258Zm.714.328a10 10 0 0 1 1.028.042a9.9 9.9 0 0 1 2.743.639c.984.39 1.89.958 2.707 1.632a10.8 10.8 0 0 1 2.091 2.328q.038.06.07.12a2.12 2.12 0 0 0-.435 2.646c-.158.114-.97.692-1.634 1.183c-.414.308-.733.557-.733.557l.581.68s.296-.276.665-.638c.572-.562 1.229-1.233 1.395-1.403a2.12 2.12 0 0 0 1.907.677a11.2 11.2 0 0 1-.013 4.046a11.4 11.4 0 0 1-1.475 3.897a12.3 12.3 0 0 1-2.079 2.587c-1.19 1.125-2.633 2.022-4.306 2.531a10.8 10.8 0 0 1-3.973.484a11 11 0 0 1-3.057-.652a3.3 3.3 0 0 0 1.417-2.294a3.3 3.3 0 0 0-.294-1.842c.18-.162.403-.363.656-.6c1.015-.955 2.353-2.303 2.353-2.303l-.47-.599s-1.63.972-2.801 1.728c-.307.198-.573.378-.777.517a3.3 3.3 0 0 0-1.516-.611a3.33 3.33 0 0 0-3.487 2.017a10 10 0 0 1-.695-1.078A11 11 0 0 1 .728 14.8a10 10 0 0 1-.2-1.212c-.164-1.653.103-3.258.629-4.754a13 13 0 0 1 1.087-2.288c.57-.968 1.248-1.872 2.069-2.656A11 11 0 0 1 11.808.797Zm-.147 3.257a3.84 3.84 0 0 0-3.82 3.82v2.36h-.94c-.751 0-1.377.625-1.377 1.377v3.8h1.46v-3.718h9.354v6.264H10.02v1.46h6.4c.751 0 1.377-.625 1.377-1.377v-6.43a1.39 1.39 0 0 0-1.377-1.377h-.94v-2.36a3.84 3.84 0 0 0-3.82-3.819zm0 1.46a2.37 2.37 0 0 1 2.36 2.36v2.36H9.3v-2.36a2.37 2.37 0 0 1 2.36-2.36zm10.141.392a1.253 1.253 0 0 1 1.296 1.434a1.24 1.24 0 0 1-.453.78c-.266.213-.61.318-.968.264a1.253 1.253 0 0 1-1.045-1.42a1.255 1.255 0 0 1 1.17-1.058M5.384 17.425a2.02 2.02 0 0 1 1.917 1.298c.116.3.159.628.114.967a2.015 2.015 0 0 1-2.249 1.728a2.016 2.016 0 0 1-1.727-2.25a2.02 2.02 0 0 1 1.945-1.743" />
  </svg>
</svg>

I think we might want to handle custom SVG's more delicately, extracting their viewBox values if they exist, then replace the svg tag, using the extracted viewBox value instead of the hardcoded 32px ones. I see that some of your icons in Const.ts use viewBox inline, so I imagine you've run into this issue yourself when defining built-in icons.

"Go module": `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 254.5 225"><title>file_type_go_package</title><path d="M61.949,13.068c16.06-.147,32.143,0,48.211-.062-3.81,16.408-7.466,32.862-11.261,49.277H25.548c-2.319,0-4.637.077-6.956-.093C33,45.775,47.566,29.5,61.949,13.068Z" style="fill:#f2e6c9"/><path d="M143.509,13.014h48.072c14.437,16.431,29.013,32.723,43.411,49.177-9.274.193-18.549,0-27.823.085H154.654C151.006,45.837,147.111,29.46,143.509,13.014Z" style="fill:#f2e6c9"/><path d="M110.16,13.014h33.349c3.6,16.446,7.489,32.823,11.16,49.254H98.9C102.694,45.868,106.35,29.422,110.16,13.014Z" style="fill:#efc75e"/><path d="M18.592,62.183c2.319.17,4.637.085,6.956.093H98.9q0,26.026.054,52.052a18.857,18.857,0,0,0,1.979.139h52.114a14.693,14.693,0,0,0,1.546-.108c.147-17.366,0-34.732.07-52.1h52.516c9.274-.046,18.549.108,27.823-.085V212.62H18.6Q18.592,137.405,18.592,62.183Z" style="fill:#e7bf55"/><path d="M98.9,62.291h55.769c-.062,17.366.085,34.732-.07,52.1-.518.054-1.036.093-1.546.108H100.94a18.857,18.857,0,0,1-1.971-.131C98.861,96.993,98.969,79.634,98.9,62.291Z" style="fill:#dbb551"/><rect x="34.389" y="163.682" width="72.417" height="27.885" style="fill:#f2f2f2"/><path d="M61.422,137.085c-.388,0-.487-.194-.291-.487l2.041-2.625a1.393,1.393,0,0,1,1.069-.487h34.7c.388,0,.487.291.291.584L97.582,136.6a1.481,1.481,0,0,1-.972.584Z" style="fill:#ce3262"/><path d="M46.74,146.028c-.388,0-.487-.194-.291-.487l2.041-2.625a1.393,1.393,0,0,1,1.069-.487H93.89a.447.447,0,0,1,.487.584l-.778,2.333a.85.85,0,0,1-.875.584Z" style="fill:#ce3262"/><path d="M70.264,154.971c-.388,0-.487-.291-.291-.584l1.357-2.43a1.289,1.289,0,0,1,.972-.584H91.747c.388,0,.584.291.584.681l-.194,2.333a.731.731,0,0,1-.681.681Z" style="fill:#ce3262"/><path d="M171.163,135.335c-6.124,1.556-10.3,2.722-16.33,4.28-1.462.388-1.556.487-2.819-.972a13.011,13.011,0,0,0-4.569-3.694c-6.124-3.013-12.054-2.138-17.594,1.462a20.671,20.671,0,0,0-9.918,18.469,15.242,15.242,0,0,0,13.123,15.261c6.61.875,12.151-1.462,16.525-6.415.875-1.069,1.653-2.236,2.625-3.6H133.446c-2.041,0-2.528-1.263-1.847-2.916,1.263-3.013,3.6-8.068,4.958-10.6a2.625,2.625,0,0,1,2.43-1.556h35.384c-.194,2.625-.194,5.249-.584,7.874a41.456,41.456,0,0,1-7.967,19.042c-6.995,9.234-16.136,14.97-27.7,16.525-9.526,1.263-18.374-.584-26.148-6.415A30.533,30.533,0,0,1,99.625,160.51c-1.263-10.6,1.847-20.122,8.262-28.481A43.137,43.137,0,0,1,135.1,115.212c9.137-1.653,17.886-.584,25.76,4.763A30.471,30.471,0,0,1,172.14,133.68C172.719,134.558,172.33,135.044,171.163,135.335Z" style="fill:#ce3262"/><path d="M203.338,189.09c-8.846-.194-16.913-2.722-23.719-8.554a30.485,30.485,0,0,1-10.5-18.761c-1.75-10.984,1.263-20.7,7.874-29.356,7.1-9.331,15.651-14.192,27.218-16.233,9.918-1.75,19.247-.778,27.7,4.958,7.68,5.249,12.442,12.345,13.706,21.676,1.653,13.123-2.138,23.816-11.179,32.953a44.542,44.542,0,0,1-23.329,12.442C208.49,188.7,205.866,188.8,203.338,189.09Zm23.135-39.271a27.978,27.978,0,0,0-.291-3.208,16.013,16.013,0,0,0-18.375-13.235q-.734.119-1.454.306c-9.04,2.041-14.873,7.777-17.011,16.913a16.009,16.009,0,0,0,8.943,18.374,17.82,17.82,0,0,0,15.845-.584c7.679-3.985,11.859-10.206,12.348-18.566Z" style="fill:#ce3262"/></svg>`,
"Go": `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 254.5 225"><title>file_type_go</title><path d="M-46.926,89c-.621,0-.777-.311-.466-.777l3.262-4.194a2.225,2.225,0,0,1,1.708-.777H13.026c.621,0,.777.466.466.932l-2.64,4.038a2.367,2.367,0,0,1-1.553.932Z" style="fill:#00acd7"/><path d="M-70.379,103.285c-.621,0-.777-.311-.466-.777l3.262-4.194a2.225,2.225,0,0,1,1.708-.777H4.95a.714.714,0,0,1,.777.932L4.484,102.2a1.358,1.358,0,0,1-1.4.932Z" style="fill:#00acd7"/><path d="M-32.792,117.574c-.621,0-.777-.466-.466-.932l2.174-3.883a2.06,2.06,0,0,1,1.553-.932H1.533c.621,0,.932.466.932,1.087l-.311,3.728a1.167,1.167,0,0,1-1.087,1.087Z" style="fill:#00acd7"/><path d="M128.426,86.2c-9.785,2.485-16.464,4.349-26.093,6.834-2.33.621-2.485.777-4.5-1.553-2.33-2.64-4.038-4.349-7.3-5.9-9.785-4.815-19.259-3.417-28.112,2.33-10.561,6.834-16,16.929-15.842,29.51.155,12.425,8.7,22.676,20.968,24.385,10.561,1.4,19.414-2.33,26.4-10.251,1.4-1.708,2.64-3.572,4.194-5.747H68.163c-3.262,0-4.038-2.019-2.951-4.659,2.019-4.815,5.747-12.891,7.921-16.929a4.194,4.194,0,0,1,3.883-2.485h56.535c-.311,4.194-.311,8.387-.932,12.581a66.239,66.239,0,0,1-12.736,30.442C108.7,159.51,94.1,168.673,75.618,171.158c-15.221,2.019-29.355-.932-41.78-10.251a48.785,48.785,0,0,1-19.725-34.48c-2.019-16.929,2.951-32.15,13.2-45.508C38.342,66.475,52.942,57.312,70.8,54.05c14.6-2.64,28.578-.932,41.159,7.61a48.686,48.686,0,0,1,18.017,21.9C130.911,84.958,130.289,85.735,128.426,86.2Z" style="fill:#00acd7"/><path d="M179.835,172.09c-14.134-.311-27.025-4.349-37.9-13.668a48.711,48.711,0,0,1-16.774-29.976c-2.8-17.551,2.019-33.082,12.581-46.905,11.338-14.91,25.006-22.676,43.488-25.938,15.842-2.8,30.753-1.243,44.265,7.921,12.27,8.387,19.88,19.725,21.9,34.635,2.64,20.968-3.417,38.052-17.861,52.652a71.17,71.17,0,0,1-37.276,19.88C188.067,171.469,183.874,171.624,179.835,172.09ZM216.8,109.343a44.7,44.7,0,0,0-.466-5.125c-2.8-15.376-16.929-24.074-31.684-20.657-14.444,3.262-23.763,12.425-27.18,27.025a25.579,25.579,0,0,0,14.289,29.355c8.542,3.728,17.085,3.262,25.317-.932C209.345,132.64,216.024,122.7,216.8,109.343Z" style="fill:#00acd7"/></svg>`,

I think handling <svg> tags will be pretty crucial for custom icons since they come in so many sizes and varieties.

Footnotes

  1. Simple Icons (Caddy)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions