Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions icons.http
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
###
GET https://cdn.jsdelivr.net/npm/simple-icons@v5/icons/figma.svg
GET https://cdn.jsdelivr.net/npm/simple-icons@14.0.0/icons/figma.svg

###
GET https://raw.githubusercontent.com/simple-icons/simple-icons/develop/_data/simple-icons.json
GET https://raw.githubusercontent.com/simple-icons/simple-icons/14.0.0/_data/simple-icons.json

###
GET https://cdn.simpleicons.org/figma
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ export * from './types/cloud'
export * from './types/options'
export * from './types/simple_icon'
export * from './utils/fetch_simple_icons'
export {getSlug} from './utils/get_slug'
export * from './utils/get_slug'
64 changes: 39 additions & 25 deletions src/utils/fetch_simple_icons.test.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
// make real network requests
import 'isomorphic-fetch'
import {fetchSimpleIcons} from './fetch_simple_icons'
import {
fetchSimpleIcons,
fetchSimpleIconText,
getSimpleIconFromText,
} from './fetch_simple_icons'
import {SimpleIcon} from '../types/simple_icon'

export const slugs = [
'amazonaws',
'android',
'androidstudio',
'antdesign',
'azuredevops',
'css3',
'cypress',
'dart',
Expand All @@ -20,7 +23,6 @@ export const slugs = [
'github',
'gitlab',
'html5',
'java',
'javascript',
'jest',
'jira',
Expand All @@ -39,31 +41,43 @@ export const slugs = [
'testinglibrary',
'typescript',
'vercel',
'visualstudiocode',
]
const figmaText = `<svg fill="#F24E1E" role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Figma</title><path d="M15.852 8.981h-4.588V0h4.588c2.476 0 4.49 2.014 4.49 4.49s-2.014 4.491-4.49 4.491zM12.735 7.51h3.117c1.665 0 3.019-1.355 3.019-3.019s-1.355-3.019-3.019-3.019h-3.117V7.51zm0 1.471H8.148c-2.476 0-4.49-2.014-4.49-4.49S5.672 0 8.148 0h4.588v8.981zm-4.587-7.51c-1.665 0-3.019 1.355-3.019 3.019s1.354 3.02 3.019 3.02h3.117V1.471H8.148zm4.587 15.019H8.148c-2.476 0-4.49-2.014-4.49-4.49s2.014-4.49 4.49-4.49h4.588v8.98zM8.148 8.981c-1.665 0-3.019 1.355-3.019 3.019s1.355 3.019 3.019 3.019h3.117V8.981H8.148zM8.172 24c-2.489 0-4.515-2.014-4.515-4.49s2.014-4.49 4.49-4.49h4.588v4.441c0 2.503-2.047 4.539-4.563 4.539zm-.024-7.51a3.023 3.023 0 0 0-3.019 3.019c0 1.665 1.365 3.019 3.044 3.019 1.705 0 3.093-1.376 3.093-3.068v-2.97H8.148zm7.704 0h-.098c-2.476 0-4.49-2.014-4.49-4.49s2.014-4.49 4.49-4.49h.098c2.476 0 4.49 2.014 4.49 4.49s-2.014 4.49-4.49 4.49zm-.097-7.509c-1.665 0-3.019 1.355-3.019 3.019s1.355 3.019 3.019 3.019h.098c1.665 0 3.019-1.355 3.019-3.019s-1.355-3.019-3.019-3.019h-.098z"/></svg>`

describe('fetchIcons', () => {
it('returns correctly formed icons', async () => {
const icons = await fetchSimpleIcons({slugs})
expect(Object.keys(icons.simpleIcons)).toHaveLength(slugs.length)
for (const icon of Object.values(icons.simpleIcons)) {
expect(icon.slug).toBeTruthy()
expect(typeof icon.slug).toBe('string')
expect(icon.slug).not.toBe('')

expect(icon.path).toBeTruthy()
expect(typeof icon.path).toBe('string')
expect(icon.path).not.toBe('')
describe('fetchSimpleIcons', () => {
it("fetches 'figma' icon", async () => {
const text = await fetchSimpleIconText('figma')
expect(text).toBe(figmaText)
})
it('extracts simple icons from res text', () => {
const resText = figmaText

expect(icon.hex).toBeTruthy()
expect(typeof icon.hex).toBe('string')
expect(icon.hex).not.toBe('')
const icon = getSimpleIconFromText('figma', resText)

const hexValues = Object.values(icons.simpleIcons).map((icon) => icon.hex)
const allBlackHex = hexValues.every(
(hex) => hex === '#000' || hex === '#000000'
)
expect(allBlackHex).toBe(false)
expect(icon).toMatchInlineSnapshot(`
Object {
"hex": "#F24E1E",
"path": "M15.852 8.981h-4.588V0h4.588c2.476 0 4.49 2.014 4.49 4.49s-2.014 4.491-4.49 4.491zM12.735 7.51h3.117c1.665 0 3.019-1.355 3.019-3.019s-1.355-3.019-3.019-3.019h-3.117V7.51zm0 1.471H8.148c-2.476 0-4.49-2.014-4.49-4.49S5.672 0 8.148 0h4.588v8.981zm-4.587-7.51c-1.665 0-3.019 1.355-3.019 3.019s1.354 3.02 3.019 3.02h3.117V1.471H8.148zm4.587 15.019H8.148c-2.476 0-4.49-2.014-4.49-4.49s2.014-4.49 4.49-4.49h4.588v8.98zM8.148 8.981c-1.665 0-3.019 1.355-3.019 3.019s1.355 3.019 3.019 3.019h3.117V8.981H8.148zM8.172 24c-2.489 0-4.515-2.014-4.515-4.49s2.014-4.49 4.49-4.49h4.588v4.441c0 2.503-2.047 4.539-4.563 4.539zm-.024-7.51a3.023 3.023 0 0 0-3.019 3.019c0 1.665 1.365 3.019 3.044 3.019 1.705 0 3.093-1.376 3.093-3.068v-2.97H8.148zm7.704 0h-.098c-2.476 0-4.49-2.014-4.49-4.49s2.014-4.49 4.49-4.49h.098c2.476 0 4.49 2.014 4.49 4.49s-2.014 4.49-4.49 4.49zm-.097-7.509c-1.665 0-3.019 1.355-3.019 3.019s1.355 3.019 3.019 3.019h.098c1.665 0 3.019-1.355 3.019-3.019s-1.355-3.019-3.019-3.019h-.098z",
"slug": "figma",
"title": "Figma",
}
`)
})
it('fetches icons with valid properties', async () => {
const res = await fetchSimpleIcons({slugs})
const icons = Object.values(res.simpleIcons)
const errors: SimpleIcon[] = []
let isAllBlack = true
for (const icon of icons) {
if (icon.hex !== '#000' && icon.hex !== '#000000') {
isAllBlack = false
}
if (!icon.hex || !icon.path || !icon.slug || !icon.title) {
errors.push(icon)
}
}
expect(isAllBlack).toBe(false)
expect(icons).toHaveLength(slugs.length)
expect(errors).toEqual([])
})
})
87 changes: 62 additions & 25 deletions src/utils/fetch_simple_icons.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,69 @@
import {SimpleIcon} from '../types/simple_icon'
import {getSlugsPath} from './get_slugs_path'
import {getSlugHexs} from './get_slug_hexs'
import type {SimpleIcon} from '../types/simple_icon'

export const extractHtmlProperty = (
str: string,
property: string,
matchType: '>' | '='
) => {
const propIndex = str.indexOf(property)
if (propIndex === -1) return ''
if (matchType === '=') {
const eqIndex = str.indexOf('=', propIndex + property.length)
if (eqIndex === -1) return ''
const startIndex = eqIndex + 2
const endIndex = str.indexOf('"', startIndex)
if (startIndex >= endIndex) return ''
return str.substring(startIndex, endIndex)
}
if (matchType === '>') {
const gtIndex = str.indexOf('>', propIndex + property.length)
if (gtIndex === -1) return ''
const startIndex = gtIndex + 1
const endIndex = str.indexOf('</', startIndex)
if (startIndex >= endIndex) return ''
return str.substring(startIndex, endIndex)
}
return ''
}

export const getSimpleIconFromText = (
slug: string,
resText: string
): SimpleIcon => {
return {
slug,
hex: extractHtmlProperty(resText, 'fill', '='),
title: extractHtmlProperty(resText, 'title', '>'),
path: extractHtmlProperty(resText, 'd', '='),
}
}

export const fetchSimpleIconText = async (slug: string) => {
const res = await fetch(`https://cdn.simpleicons.org/${slug}`)
const text = await res.text()
return text
}

const cache: Record<string, SimpleIcon> = {}

export const fetchSimpleIcons = async ({slugs}: {slugs: string[]}) => {
const [paths, {hexs, cache}] = await Promise.all([
getSlugsPath(slugs),
getSlugHexs(slugs),
])
const map = {} as any
hexs.forEach((hex) => {
map[hex.slug] = hex
})
paths.forEach((path) => {
map[path.slug].path = path.path
})
slugs.forEach((s) => {
const o = map[s]
if (!o.hex || !o.path) {
if (process.env.NODE_ENV !== 'production') {
console.error(
`'react-icon-cloud/fetchSimpleIcons': the response of ${o.slug} was malformed and it will be ignored.`
)
}
delete map[s]
const simpleIcons: Record<string, SimpleIcon> = {}
const promises: Promise<void>[] = []
for (const slug of slugs) {
if (cache[slug]) {
simpleIcons[slug] = cache[slug]
continue
}
})
promises.push(
fetchSimpleIconText(slug).then((text) => {
const icon = getSimpleIconFromText(slug, text)
simpleIcons[slug] = icon
})
)
}
await Promise.allSettled(promises)
return {
simpleIcons: map as Record<string, SimpleIcon>,
simpleIcons,
allIcon: cache!,
}
}
45 changes: 0 additions & 45 deletions src/utils/get_slug_hexs.ts

This file was deleted.

35 changes: 0 additions & 35 deletions src/utils/get_slugs_path.ts

This file was deleted.

5 changes: 0 additions & 5 deletions src/utils/svg_to_path.ts

This file was deleted.

Loading