mirror of
https://github.com/badges/shields.git
synced 2025-04-18 19:44:04 +03:00
feat(logos): support auto-sizing mode (#9191)
Co-authored-by: chris48s <git@chris-shaw.dev>
This commit is contained in:
parent
e8671be7f2
commit
915ab742d9
5
badge-maker/lib/constants.js
Normal file
5
badge-maker/lib/constants.js
Normal file
@ -0,0 +1,5 @@
|
||||
const DEFAULT_LOGO_HEIGHT = 14
|
||||
|
||||
module.exports = {
|
||||
DEFAULT_LOGO_HEIGHT,
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
const { normalizeColor, toSvgColor } = require('./color')
|
||||
const badgeRenderers = require('./badge-renderers')
|
||||
const { stripXmlWhitespace } = require('./xml')
|
||||
const { DEFAULT_LOGO_HEIGHT } = require('./constants')
|
||||
|
||||
/*
|
||||
note: makeBadge() is fairly thinly wrapped so if we are making changes here
|
||||
@ -17,6 +18,7 @@ module.exports = function makeBadge({
|
||||
labelColor,
|
||||
logo,
|
||||
logoPosition,
|
||||
logoSize,
|
||||
logoWidth,
|
||||
links = ['', ''],
|
||||
}) {
|
||||
@ -45,7 +47,7 @@ module.exports = function makeBadge({
|
||||
throw new Error(`Unknown badge style: '${style}'`)
|
||||
}
|
||||
|
||||
logoWidth = +logoWidth || (logo ? 14 : 0)
|
||||
logoWidth = +logoWidth || (logo ? DEFAULT_LOGO_HEIGHT : 0)
|
||||
|
||||
return stripXmlWhitespace(
|
||||
render({
|
||||
@ -55,6 +57,7 @@ module.exports = function makeBadge({
|
||||
logo,
|
||||
logoPosition,
|
||||
logoWidth,
|
||||
logoSize,
|
||||
logoPadding: logo && label.length ? 3 : 0,
|
||||
color: toSvgColor(color),
|
||||
labelColor: toSvgColor(labelColor),
|
||||
|
@ -377,6 +377,7 @@ describe('BaseService', function () {
|
||||
namedLogo: undefined,
|
||||
logo: undefined,
|
||||
logoWidth: undefined,
|
||||
logoSize: undefined,
|
||||
logoPosition: undefined,
|
||||
links: [],
|
||||
labelColor: undefined,
|
||||
|
@ -2,7 +2,8 @@ import {
|
||||
decodeDataUrlFromQueryParam,
|
||||
prepareNamedLogo,
|
||||
} from '../../lib/logos.js'
|
||||
import { svg2base64 } from '../../lib/svg-helpers.js'
|
||||
import { svg2base64, getIconSize } from '../../lib/svg-helpers.js'
|
||||
import { DEFAULT_LOGO_HEIGHT } from '../../badge-maker/lib/constants.js'
|
||||
import coalesce from './coalesce.js'
|
||||
import toArray from './to-array.js'
|
||||
|
||||
@ -56,6 +57,7 @@ export default function coalesceBadge(
|
||||
let {
|
||||
logoWidth: overrideLogoWidth,
|
||||
logoPosition: overrideLogoPosition,
|
||||
logoSize: overrideLogoSize,
|
||||
color: overrideColor,
|
||||
labelColor: overrideLabelColor,
|
||||
} = overrides
|
||||
@ -87,6 +89,7 @@ export default function coalesceBadge(
|
||||
logoSvg: serviceLogoSvg,
|
||||
namedLogo: serviceNamedLogo,
|
||||
logoColor: serviceLogoColor,
|
||||
logoSize: serviceLogoSize,
|
||||
logoWidth: serviceLogoWidth,
|
||||
logoPosition: serviceLogoPosition,
|
||||
link: serviceLink,
|
||||
@ -119,7 +122,12 @@ export default function coalesceBadge(
|
||||
style = 'flat'
|
||||
}
|
||||
|
||||
let namedLogo, namedLogoColor, logoWidth, logoPosition, logoSvgBase64
|
||||
let namedLogo,
|
||||
namedLogoColor,
|
||||
logoSize,
|
||||
logoWidth,
|
||||
logoPosition,
|
||||
logoSvgBase64
|
||||
if (overrideLogo) {
|
||||
// `?logo=` could be a named logo or encoded svg.
|
||||
const overrideLogoSvgBase64 = decodeDataUrlFromQueryParam(overrideLogo)
|
||||
@ -133,6 +141,7 @@ export default function coalesceBadge(
|
||||
}
|
||||
// If the logo has been overridden it does not make sense to inherit the
|
||||
// original width or position.
|
||||
logoSize = overrideLogoSize
|
||||
logoWidth = overrideLogoWidth
|
||||
logoPosition = overrideLogoPosition
|
||||
} else {
|
||||
@ -145,13 +154,21 @@ export default function coalesceBadge(
|
||||
)
|
||||
namedLogoColor = coalesce(overrideLogoColor, serviceLogoColor)
|
||||
}
|
||||
logoSize = coalesce(overrideLogoSize, serviceLogoSize)
|
||||
logoWidth = coalesce(overrideLogoWidth, serviceLogoWidth)
|
||||
logoPosition = coalesce(overrideLogoPosition, serviceLogoPosition)
|
||||
}
|
||||
if (namedLogo) {
|
||||
const iconSize = getIconSize(String(namedLogo).toLowerCase())
|
||||
|
||||
if (!logoWidth && iconSize && logoSize === 'auto') {
|
||||
logoWidth = (iconSize.width / iconSize.height) * DEFAULT_LOGO_HEIGHT
|
||||
}
|
||||
|
||||
logoSvgBase64 = prepareNamedLogo({
|
||||
name: namedLogo,
|
||||
color: namedLogoColor,
|
||||
size: logoSize,
|
||||
style,
|
||||
})
|
||||
}
|
||||
@ -179,6 +196,7 @@ export default function coalesceBadge(
|
||||
logo: logoSvgBase64,
|
||||
logoWidth,
|
||||
logoPosition,
|
||||
logoSize,
|
||||
links: toArray(overrideLink || serviceLink),
|
||||
cacheLengthSeconds: coalesce(serviceCacheSeconds, defaultCacheSeconds),
|
||||
}
|
||||
|
@ -260,6 +260,20 @@ describe('coalesceBadge', function () {
|
||||
})
|
||||
})
|
||||
|
||||
describe('Logo size', function () {
|
||||
it('overrides the logoSize', function () {
|
||||
expect(coalesceBadge({ logoSize: 'auto' }, {}, {})).to.include({
|
||||
logoSize: 'auto',
|
||||
})
|
||||
})
|
||||
|
||||
it('applies the logo size', function () {
|
||||
expect(
|
||||
coalesceBadge({}, { namedLogo: 'npm', logoSize: 'auto' }, {}),
|
||||
).to.include({ logoSize: 'auto' })
|
||||
})
|
||||
})
|
||||
|
||||
describe('Logo width', function () {
|
||||
it('overrides the logoWidth', function () {
|
||||
expect(coalesceBadge({ logoWidth: 20 }, {}, {})).to.include({
|
||||
|
@ -9,6 +9,7 @@ const globalParamRefs = [
|
||||
{ $ref: '#/components/parameters/style' },
|
||||
{ $ref: '#/components/parameters/logo' },
|
||||
{ $ref: '#/components/parameters/logoColor' },
|
||||
{ $ref: '#/components/parameters/logoSize' },
|
||||
{ $ref: '#/components/parameters/label' },
|
||||
{ $ref: '#/components/parameters/labelColor' },
|
||||
{ $ref: '#/components/parameters/color' },
|
||||
@ -140,6 +141,17 @@ function category2openapi({ category, services, sort = false }) {
|
||||
},
|
||||
example: 'violet',
|
||||
},
|
||||
logoSize: {
|
||||
name: 'logoSize',
|
||||
in: 'query',
|
||||
required: false,
|
||||
description:
|
||||
'Make icons adaptively resize by setting `auto`. Useful for some wider logos like `amd` and `amg`. Supported for simple-icons logos only.',
|
||||
schema: {
|
||||
type: 'string',
|
||||
},
|
||||
example: 'auto',
|
||||
},
|
||||
label: {
|
||||
name: 'label',
|
||||
in: 'query',
|
||||
|
@ -93,6 +93,17 @@ const expected = {
|
||||
schema: { type: 'string' },
|
||||
example: 'violet',
|
||||
},
|
||||
logoSize: {
|
||||
name: 'logoSize',
|
||||
in: 'query',
|
||||
required: false,
|
||||
description:
|
||||
'Make icons adaptively resize by setting `auto`. Useful for some wider logos like `amd` and `amg`. Supported for simple-icons logos only.',
|
||||
schema: {
|
||||
type: 'string',
|
||||
},
|
||||
example: 'auto',
|
||||
},
|
||||
label: {
|
||||
name: 'label',
|
||||
in: 'query',
|
||||
@ -158,6 +169,7 @@ const expected = {
|
||||
{ $ref: '#/components/parameters/style' },
|
||||
{ $ref: '#/components/parameters/logo' },
|
||||
{ $ref: '#/components/parameters/logoColor' },
|
||||
{ $ref: '#/components/parameters/logoSize' },
|
||||
{ $ref: '#/components/parameters/label' },
|
||||
{ $ref: '#/components/parameters/labelColor' },
|
||||
{ $ref: '#/components/parameters/color' },
|
||||
@ -213,6 +225,7 @@ const expected = {
|
||||
{ $ref: '#/components/parameters/style' },
|
||||
{ $ref: '#/components/parameters/logo' },
|
||||
{ $ref: '#/components/parameters/logoColor' },
|
||||
{ $ref: '#/components/parameters/logoSize' },
|
||||
{ $ref: '#/components/parameters/label' },
|
||||
{ $ref: '#/components/parameters/labelColor' },
|
||||
{ $ref: '#/components/parameters/color' },
|
||||
|
@ -1,5 +1,4 @@
|
||||
import * as originalSimpleIcons from 'simple-icons/icons'
|
||||
import { svg2base64 } from './svg-helpers.js'
|
||||
|
||||
function loadSimpleIcons() {
|
||||
const simpleIcons = {}
|
||||
@ -16,10 +15,10 @@ function loadSimpleIcons() {
|
||||
const icon = originalSimpleIcons[key]
|
||||
const { title, slug, hex } = icon
|
||||
|
||||
icon.base64 = {
|
||||
default: svg2base64(icon.svg.replace('<svg', `<svg fill="#${hex}"`)),
|
||||
light: svg2base64(icon.svg.replace('<svg', '<svg fill="whitesmoke"')),
|
||||
dark: svg2base64(icon.svg.replace('<svg', '<svg fill="#333"')),
|
||||
icon.styles = {
|
||||
default: icon.svg.replace('<svg', `<svg fill="#${hex}"`),
|
||||
light: icon.svg.replace('<svg', '<svg fill="whitesmoke"'),
|
||||
dark: icon.svg.replace('<svg', '<svg fill="#333"'),
|
||||
}
|
||||
|
||||
// There are a few instances where multiple icons have the same title
|
||||
|
@ -8,7 +8,7 @@ describe('loadSimpleIcons', function () {
|
||||
})
|
||||
|
||||
it('prepares three color themes', function () {
|
||||
expect(simpleIcons.sentry.base64).to.have.all.keys(
|
||||
expect(simpleIcons.sentry.styles).to.have.all.keys(
|
||||
'default',
|
||||
'light',
|
||||
'dark',
|
||||
|
35
lib/logos.js
35
lib/logos.js
@ -5,7 +5,7 @@ import {
|
||||
normalizeColor,
|
||||
} from '../badge-maker/lib/color.js'
|
||||
import coalesce from '../core/base-service/coalesce.js'
|
||||
import { svg2base64 } from './svg-helpers.js'
|
||||
import { svg2base64, getIconSize, resetIconPosition } from './svg-helpers.js'
|
||||
import loadLogos from './load-logos.js'
|
||||
import loadSimpleIcons from './load-simple-icons.js'
|
||||
const logos = loadLogos()
|
||||
@ -88,25 +88,42 @@ function getSimpleIconStyle({ icon, style }) {
|
||||
return 'default'
|
||||
}
|
||||
|
||||
function getSimpleIcon({ name, color, style }) {
|
||||
// The `size` parameter is used to determine whether the icon should be resized
|
||||
// to fit the badge. If `size` is 'auto', the icon will be resized to fit the
|
||||
// badge. If `size` is not 'auto', the icon will be displayed at its original.
|
||||
// https://github.com/badges/shields/pull/9191
|
||||
function getSimpleIcon({ name, color, style, size }) {
|
||||
const key = name === 'travis' ? 'travis-ci' : name.replace(/ /g, '-')
|
||||
|
||||
if (!(key in simpleIcons)) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
let iconSvg
|
||||
|
||||
const svgColor = toSvgColor(color)
|
||||
if (svgColor) {
|
||||
return svg2base64(
|
||||
simpleIcons[key].svg.replace('<svg', `<svg fill="${svgColor}"`),
|
||||
)
|
||||
iconSvg = simpleIcons[key].svg.replace('<svg', `<svg fill="${svgColor}"`)
|
||||
} else {
|
||||
const iconStyle = getSimpleIconStyle({ icon: simpleIcons[key], style })
|
||||
return simpleIcons[key].base64[iconStyle]
|
||||
iconSvg = simpleIcons[key].styles[iconStyle]
|
||||
}
|
||||
|
||||
if (size === 'auto') {
|
||||
const { width: iconWidth, height: iconHeight } = getIconSize(key)
|
||||
|
||||
if (iconWidth > iconHeight) {
|
||||
const path = resetIconPosition(simpleIcons[key].path)
|
||||
iconSvg = iconSvg
|
||||
.replace('viewBox="0 0 24 24"', `viewBox="0 0 24 ${iconHeight}"`)
|
||||
.replace(/<path d=".*"\/>/, `<path d="${path}"/>`)
|
||||
}
|
||||
}
|
||||
|
||||
return svg2base64(iconSvg)
|
||||
}
|
||||
|
||||
function prepareNamedLogo({ name, color, style }) {
|
||||
function prepareNamedLogo({ name, color, style, size }) {
|
||||
if (typeof name !== 'string') {
|
||||
return undefined
|
||||
}
|
||||
@ -118,7 +135,8 @@ function prepareNamedLogo({ name, color, style }) {
|
||||
}
|
||||
|
||||
return (
|
||||
getShieldsIcon({ name, color }) || getSimpleIcon({ name, color, style })
|
||||
getShieldsIcon({ name, color }) ||
|
||||
getSimpleIcon({ name, color, style, size })
|
||||
)
|
||||
}
|
||||
|
||||
@ -131,6 +149,7 @@ function makeLogo(defaultNamedLogo, overrides) {
|
||||
name: coalesce(overrides.logo, defaultNamedLogo),
|
||||
color: overrides.logoColor,
|
||||
style: overrides.style,
|
||||
size: overrides.logoSize,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -57,6 +57,14 @@ describe('Logo helpers', function () {
|
||||
given({ name: 'github', color: 'red' }).expect(
|
||||
'data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjZTA1ZDQ0IiByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48dGl0bGU+R2l0SHViPC90aXRsZT48cGF0aCBkPSJNMTIgLjI5N2MtNi42MyAwLTEyIDUuMzczLTEyIDEyIDAgNS4zMDMgMy40MzggOS44IDguMjA1IDExLjM4NS42LjExMy44Mi0uMjU4LjgyLS41NzcgMC0uMjg1LS4wMS0xLjA0LS4wMTUtMi4wNC0zLjMzOC43MjQtNC4wNDItMS42MS00LjA0Mi0xLjYxQzQuNDIyIDE4LjA3IDMuNjMzIDE3LjcgMy42MzMgMTcuN2MtMS4wODctLjc0NC4wODQtLjcyOS4wODQtLjcyOSAxLjIwNS4wODQgMS44MzggMS4yMzYgMS44MzggMS4yMzYgMS4wNyAxLjgzNSAyLjgwOSAxLjMwNSAzLjQ5NS45OTguMTA4LS43NzYuNDE3LTEuMzA1Ljc2LTEuNjA1LTIuNjY1LS4zLTUuNDY2LTEuMzMyLTUuNDY2LTUuOTMgMC0xLjMxLjQ2NS0yLjM4IDEuMjM1LTMuMjItLjEzNS0uMzAzLS41NC0xLjUyMy4xMDUtMy4xNzYgMCAwIDEuMDA1LS4zMjIgMy4zIDEuMjMuOTYtLjI2NyAxLjk4LS4zOTkgMy0uNDA1IDEuMDIuMDA2IDIuMDQuMTM4IDMgLjQwNSAyLjI4LTEuNTUyIDMuMjg1LTEuMjMgMy4yODUtMS4yMy42NDUgMS42NTMuMjQgMi44NzMuMTIgMy4xNzYuNzY1Ljg0IDEuMjMgMS45MSAxLjIzIDMuMjIgMCA0LjYxLTIuODA1IDUuNjI1LTUuNDc1IDUuOTIuNDIuMzYuODEgMS4wOTYuODEgMi4yMiAwIDEuNjA2LS4wMTUgMi44OTYtLjAxNSAzLjI4NiAwIC4zMTUuMjEuNjkuODI1LjU3QzIwLjU2NSAyMi4wOTIgMjQgMTcuNTkyIDI0IDEyLjI5N2MwLTYuNjI3LTUuMzczLTEyLTEyLTEyIi8+PC9zdmc+',
|
||||
)
|
||||
// use simple icon with auto logo size
|
||||
given({ name: 'amd', size: 'auto' }).expect(
|
||||
'data:image/svg+xml;base64,PHN2ZyBmaWxsPSJ3aGl0ZXNtb2tlIiByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNCA1LjcyNTk5OTk5OTk5OTk5OSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48dGl0bGU+QU1EPC90aXRsZT48cGF0aCBkPSJNMTguMzI0IDBMMTkuODgzIDEuNTZIMjIuNDM5VjQuMTE3TDI0IDUuNjc3VjBaTTIgMC4zODNMMCA1LjM0M0gxLjMwOUwxLjY3OSA0LjM2MUgzLjlMNC4zMDggNS4zNDNINS42NDZMMy40MzIgMC4zODNaTTYuMjA5IDAuMzgzVjUuMzM4SDcuNDQ3VjIuMjQ2TDguNzg1IDMuODA4SDguOTczTDEwLjMxMSAyLjI1MlY1LjM0M0gxMS41NDlWMC4zODNIMTAuNDdMOC44NzggMi4yMjhMNy4yODcgMC4zODNaTTEyLjQ5MiAwLjM4M1Y1LjM0M0gxNC41NDlDMTYuNTI4IDUuMzQzIDE3LjQyOSA0LjI5NyAxNy40MjkgMi44NzFDMTcuNDI5IDEuNTExIDE2LjQ5MiAwLjM4MyAxNC42ODIgMC4zODNaTTEzLjcyOSAxLjI5M0gxNC41MjFDMTUuNjkxIDEuMjkzIDE2LjE1MSAyLjAwNCAxNi4xNTEgMi44NjNDMTYuMTUxIDMuNTkxIDE1Ljc3OSA0LjQzNSAxNC41MzUgNC40MzVIMTMuNzI5Wk0yLjc0NCAxLjU2NkwzLjUzNSAzLjQ5OEgyLjAwOFpNMTkuODgxIDEuODczTDE4LjI3NyAzLjQ3NlY1LjcyNkgyMC41MjNMMjIuMTI3IDQuMTE5SDE5Ljg4MVoiLz48L3N2Zz4=',
|
||||
)
|
||||
// use simple icon with color & auto logo size
|
||||
given({ name: 'amd', color: 'white', size: 'auto' }).expect(
|
||||
'data:image/svg+xml;base64,PHN2ZyBmaWxsPSJ3aGl0ZSIgcm9sZT0iaW1nIiB2aWV3Qm94PSIwIDAgMjQgNS43MjU5OTk5OTk5OTk5OTkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHRpdGxlPkFNRDwvdGl0bGU+PHBhdGggZD0iTTE4LjMyNCAwTDE5Ljg4MyAxLjU2SDIyLjQzOVY0LjExN0wyNCA1LjY3N1YwWk0yIDAuMzgzTDAgNS4zNDNIMS4zMDlMMS42NzkgNC4zNjFIMy45TDQuMzA4IDUuMzQzSDUuNjQ2TDMuNDMyIDAuMzgzWk02LjIwOSAwLjM4M1Y1LjMzOEg3LjQ0N1YyLjI0Nkw4Ljc4NSAzLjgwOEg4Ljk3M0wxMC4zMTEgMi4yNTJWNS4zNDNIMTEuNTQ5VjAuMzgzSDEwLjQ3TDguODc4IDIuMjI4TDcuMjg3IDAuMzgzWk0xMi40OTIgMC4zODNWNS4zNDNIMTQuNTQ5QzE2LjUyOCA1LjM0MyAxNy40MjkgNC4yOTcgMTcuNDI5IDIuODcxQzE3LjQyOSAxLjUxMSAxNi40OTIgMC4zODMgMTQuNjgyIDAuMzgzWk0xMy43MjkgMS4yOTNIMTQuNTIxQzE1LjY5MSAxLjI5MyAxNi4xNTEgMi4wMDQgMTYuMTUxIDIuODYzQzE2LjE1MSAzLjU5MSAxNS43NzkgNC40MzUgMTQuNTM1IDQuNDM1SDEzLjcyOVpNMi43NDQgMS41NjZMMy41MzUgMy40OThIMi4wMDhaTTE5Ljg4MSAxLjg3M0wxOC4yNzcgMy40NzZWNS43MjZIMjAuNTIzTDIyLjEyNyA0LjExOUgxOS44ODFaIi8+PC9zdmc+',
|
||||
)
|
||||
|
||||
// use travis shield icon
|
||||
given({ name: 'travis' }).expect(
|
||||
|
@ -1,7 +1,38 @@
|
||||
import SVGPathCommander from 'svg-path-commander'
|
||||
import loadSimpleIcons from './load-simple-icons.js'
|
||||
|
||||
function svg2base64(svg) {
|
||||
return `data:image/svg+xml;base64,${Buffer.from(svg.trim()).toString(
|
||||
'base64',
|
||||
)}`
|
||||
}
|
||||
|
||||
export { svg2base64 }
|
||||
function getIconSize(iconKey) {
|
||||
const simpleIcons = loadSimpleIcons()
|
||||
|
||||
if (!(iconKey in simpleIcons)) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
const {
|
||||
width,
|
||||
height,
|
||||
x: x0,
|
||||
y: y0,
|
||||
x2: x1,
|
||||
y2: y1,
|
||||
} = SVGPathCommander.getPathBBox(simpleIcons[iconKey].path)
|
||||
|
||||
return { width, height, x0, y0, x1, y1 }
|
||||
}
|
||||
|
||||
function resetIconPosition(path) {
|
||||
const { x: offsetX, y: offsetY } = SVGPathCommander.getPathBBox(path)
|
||||
const pathReset = new SVGPathCommander(path)
|
||||
.transform({ translate: [-offsetX, -offsetY] })
|
||||
.toString()
|
||||
|
||||
return pathReset
|
||||
}
|
||||
|
||||
export { svg2base64, getIconSize, resetIconPosition }
|
||||
|
18
package-lock.json
generated
18
package-lock.json
generated
@ -53,6 +53,7 @@
|
||||
"semver": "~7.6.0",
|
||||
"simple-icons": "11.12.0",
|
||||
"smol-toml": "1.1.4",
|
||||
"svg-path-commander": "^2.0.9",
|
||||
"webextension-store-meta": "^1.2.1",
|
||||
"xpath": "~0.0.34"
|
||||
},
|
||||
@ -4893,6 +4894,11 @@
|
||||
"node": ">=14.16"
|
||||
}
|
||||
},
|
||||
"node_modules/@thednp/dommatrix": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@thednp/dommatrix/-/dommatrix-2.0.6.tgz",
|
||||
"integrity": "sha512-DXQq4Rs/akYzeXYGkNy3KiJ4JoD8+SYr1QRWTXtAGoZ0+vJcyBt0aeqA1K4CxPaBaIfKdOTE+Te1HV9sAQ4I4A=="
|
||||
},
|
||||
"node_modules/@tokenizer/token": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz",
|
||||
@ -27281,6 +27287,18 @@
|
||||
"integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/svg-path-commander": {
|
||||
"version": "2.0.9",
|
||||
"resolved": "https://registry.npmjs.org/svg-path-commander/-/svg-path-commander-2.0.9.tgz",
|
||||
"integrity": "sha512-VfRLznHewlpQvuahtBK0MT/PlWAapbTx8RSytqgaVwD3US2keKcc3WYYlBBk4vIOR+jB3nQu/NAVlWHKlo0Fjw==",
|
||||
"dependencies": {
|
||||
"@thednp/dommatrix": "^2.0.6"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16",
|
||||
"pnpm": ">=8.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/svgo": {
|
||||
"version": "2.8.0",
|
||||
"resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz",
|
||||
|
@ -65,6 +65,7 @@
|
||||
"semver": "~7.6.0",
|
||||
"simple-icons": "11.12.0",
|
||||
"smol-toml": "1.1.4",
|
||||
"svg-path-commander": "^2.0.9",
|
||||
"webextension-store-meta": "^1.2.1",
|
||||
"xpath": "~0.0.34"
|
||||
},
|
||||
|
Loading…
x
Reference in New Issue
Block a user