2
0
mirror of https://github.com/iconify/iconify.git synced 2025-01-12 01:45:41 +00:00

Rewite API handling and export reusable _api.sendQuery function that can be used without adding API provider first

This commit is contained in:
Vjacheslav Trushkin 2021-09-05 19:09:25 +03:00
parent 46988cf994
commit 96ced6e5de
55 changed files with 976 additions and 953 deletions

View File

@ -1,26 +1,26 @@
import mocha from 'mocha';
import chai from 'chai';
import { FakeData, setFakeData, prepareQuery, sendQuery } from './fake-api';
import { API } from '@iconify/core/lib/api/';
import { setAPIModule } from '@iconify/core/lib/api/modules';
import { setAPIConfig } from '@iconify/core/lib/api/config';
import { coreModules } from '@iconify/core/lib/modules';
import { loadIcons } from '@iconify/core/lib/api/icons';
const expect = chai.expect;
// Set API
setAPIModule('', {
prepare: prepareQuery,
send: sendQuery,
});
coreModules.api = API;
let prefixCounter = 0;
function nextPrefix(): string {
return 'fake-api-' + prefixCounter++;
}
describe('Testing fake API', () => {
before(() => {
setAPIModule('', {
prepare: prepareQuery,
send: sendQuery,
});
});
it('Loading results', (done) => {
const provider = nextPrefix();
const prefix = nextPrefix();
@ -30,12 +30,10 @@ describe('Testing fake API', () => {
prefix,
icons: {
icon1: {
body:
'<path d="M10 20v-6h4v6h5v-8h3L12 3L2 12h3v8h5z" fill="currentColor"/>',
body: '<path d="M10 20v-6h4v6h5v-8h3L12 3L2 12h3v8h5z" fill="currentColor"/>',
},
icon2: {
body:
'<path d="M12 4a4 4 0 0 1 4 4a4 4 0 0 1-4 4a4 4 0 0 1-4-4a4 4 0 0 1 4-4m0 10c4.42 0 8 1.79 8 4v2H4v-2c0-2.21 3.58-4 8-4z" fill="currentColor"/>',
body: '<path d="M12 4a4 4 0 0 1 4 4a4 4 0 0 1-4 4a4 4 0 0 1-4-4a4 4 0 0 1 4-4m0 10c4.42 0 8 1.79 8 4v2H4v-2c0-2.21 3.58-4 8-4z" fill="currentColor"/>',
},
},
width: 24,
@ -48,7 +46,7 @@ describe('Testing fake API', () => {
setFakeData(provider, prefix, data);
// Attempt to load icons
API.loadIcons(
loadIcons(
[
provider + ':' + prefix + ':icon1',
provider + ':' + prefix + ':icon2',
@ -81,12 +79,10 @@ describe('Testing fake API', () => {
prefix,
icons: {
icon1: {
body:
'<path d="M10 20v-6h4v6h5v-8h3L12 3L2 12h3v8h5z" fill="currentColor"/>',
body: '<path d="M10 20v-6h4v6h5v-8h3L12 3L2 12h3v8h5z" fill="currentColor"/>',
},
icon2: {
body:
'<path d="M12 4a4 4 0 0 1 4 4a4 4 0 0 1-4 4a4 4 0 0 1-4-4a4 4 0 0 1 4-4m0 10c4.42 0 8 1.79 8 4v2H4v-2c0-2.21 3.58-4 8-4z" fill="currentColor"/>',
body: '<path d="M12 4a4 4 0 0 1 4 4a4 4 0 0 1-4 4a4 4 0 0 1-4-4a4 4 0 0 1 4-4m0 10c4.42 0 8 1.79 8 4v2H4v-2c0-2.21 3.58-4 8-4z" fill="currentColor"/>',
},
},
width: 24,
@ -100,7 +96,7 @@ describe('Testing fake API', () => {
// Attempt to load icons
const start = Date.now();
API.loadIcons(
loadIcons(
[
{
provider,
@ -144,8 +140,7 @@ describe('Testing fake API', () => {
prefix,
icons: {
icon1: {
body:
'<path d="M10 20v-6h4v6h5v-8h3L12 3L2 12h3v8h5z" fill="currentColor"/>',
body: '<path d="M10 20v-6h4v6h5v-8h3L12 3L2 12h3v8h5z" fill="currentColor"/>',
},
},
width: 24,
@ -161,7 +156,7 @@ describe('Testing fake API', () => {
// Attempt to load icons
let counter = 0;
API.loadIcons(
loadIcons(
[
provider + ':' + prefix + ':icon1',
provider + ':' + prefix + ':icon2',

View File

@ -13,11 +13,13 @@ import { IconifyIconName } from '@iconify/utils/lib/icon/name';
const expect = chai.expect;
// Add finders
addFinder(iconifyFinder);
addFinder(iconifyIconFinder);
describe('Testing legacy finder', () => {
before(() => {
// Add finders
addFinder(iconifyFinder);
addFinder(iconifyIconFinder);
});
it('Finding nodes', () => {
const node = getNode('finder');
node.innerHTML =

View File

@ -13,11 +13,13 @@ import { IconifyIconName } from '@iconify/utils/lib/icon/name';
const expect = chai.expect;
// Add finders
addFinder(iconifyFinder);
addFinder(iconifyIconFinder);
describe('Testing finder', () => {
before(() => {
// Add finders
addFinder(iconifyFinder);
addFinder(iconifyIconFinder);
});
it('Finding nodes', () => {
const node = getNode('finder');
node.innerHTML =

View File

@ -19,31 +19,34 @@ import { IconifyElement } from '@iconify/iconify/lib/modules/element';
const expect = chai.expect;
// Add finders
addFinder(iconifyIconFinder);
addFinder(iconifyFinder);
describe('Testing legacy renderer', () => {
// Add mentioned icons to storage
const storage = getStorage('', 'mdi');
addIconSet(storage, {
prefix: 'mdi',
icons: {
'account-box': {
body: '<path d="M6 17c0-2 4-3.1 6-3.1s6 1.1 6 3.1v1H6m9-9a3 3 0 0 1-3 3a3 3 0 0 1-3-3a3 3 0 0 1 3-3a3 3 0 0 1 3 3M3 5v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2z" fill="currentColor"/>',
before(() => {
// Add finders
addFinder(iconifyIconFinder);
addFinder(iconifyFinder);
// Add mentioned icons to storage
addIconSet(storage, {
prefix: 'mdi',
icons: {
'account-box': {
body: '<path d="M6 17c0-2 4-3.1 6-3.1s6 1.1 6 3.1v1H6m9-9a3 3 0 0 1-3 3a3 3 0 0 1-3-3a3 3 0 0 1 3-3a3 3 0 0 1 3 3M3 5v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2z" fill="currentColor"/>',
},
'account-cash': {
body: '<path d="M11 8c0 2.21-1.79 4-4 4s-4-1.79-4-4s1.79-4 4-4s4 1.79 4 4m0 6.72V20H0v-2c0-2.21 3.13-4 7-4c1.5 0 2.87.27 4 .72M24 20H13V3h11v17m-8-8.5a2.5 2.5 0 0 1 5 0a2.5 2.5 0 0 1-5 0M22 7a2 2 0 0 1-2-2h-3c0 1.11-.89 2-2 2v9a2 2 0 0 1 2 2h3c0-1.1.9-2 2-2V7z" fill="currentColor"/>',
},
'account': {
body: '<path d="M12 4a4 4 0 0 1 4 4a4 4 0 0 1-4 4a4 4 0 0 1-4-4a4 4 0 0 1 4-4m0 10c4.42 0 8 1.79 8 4v2H4v-2c0-2.21 3.58-4 8-4z" fill="currentColor"/>',
},
'home': {
body: '<path d="M10 20v-6h4v6h5v-8h3L12 3L2 12h3v8h5z" fill="currentColor"/>',
},
},
'account-cash': {
body: '<path d="M11 8c0 2.21-1.79 4-4 4s-4-1.79-4-4s1.79-4 4-4s4 1.79 4 4m0 6.72V20H0v-2c0-2.21 3.13-4 7-4c1.5 0 2.87.27 4 .72M24 20H13V3h11v17m-8-8.5a2.5 2.5 0 0 1 5 0a2.5 2.5 0 0 1-5 0M22 7a2 2 0 0 1-2-2h-3c0 1.11-.89 2-2 2v9a2 2 0 0 1 2 2h3c0-1.1.9-2 2-2V7z" fill="currentColor"/>',
},
'account': {
body: '<path d="M12 4a4 4 0 0 1 4 4a4 4 0 0 1-4 4a4 4 0 0 1-4-4a4 4 0 0 1 4-4m0 10c4.42 0 8 1.79 8 4v2H4v-2c0-2.21 3.58-4 8-4z" fill="currentColor"/>',
},
'home': {
body: '<path d="M10 20v-6h4v6h5v-8h3L12 3L2 12h3v8h5z" fill="currentColor"/>',
},
},
width: 24,
height: 24,
width: 24,
height: 24,
});
});
it('Convert placeholders to SVG', () => {

View File

@ -19,31 +19,34 @@ import { IconifyElement } from '@iconify/iconify/lib/modules/element';
const expect = chai.expect;
// Add finders
addFinder(iconifyIconFinder);
addFinder(iconifyFinder);
describe('Testing renderer', () => {
// Add mentioned icons to storage
const storage = getStorage('', 'mdi');
addIconSet(storage, {
prefix: 'mdi',
icons: {
'account-box': {
body: '<path d="M6 17c0-2 4-3.1 6-3.1s6 1.1 6 3.1v1H6m9-9a3 3 0 0 1-3 3a3 3 0 0 1-3-3a3 3 0 0 1 3-3a3 3 0 0 1 3 3M3 5v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2z" fill="currentColor"/>',
before(() => {
// Add finders
addFinder(iconifyIconFinder);
addFinder(iconifyFinder);
// Add mentioned icons to storage
addIconSet(storage, {
prefix: 'mdi',
icons: {
'account-box': {
body: '<path d="M6 17c0-2 4-3.1 6-3.1s6 1.1 6 3.1v1H6m9-9a3 3 0 0 1-3 3a3 3 0 0 1-3-3a3 3 0 0 1 3-3a3 3 0 0 1 3 3M3 5v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2z" fill="currentColor"/>',
},
'account-cash': {
body: '<path d="M11 8c0 2.21-1.79 4-4 4s-4-1.79-4-4s1.79-4 4-4s4 1.79 4 4m0 6.72V20H0v-2c0-2.21 3.13-4 7-4c1.5 0 2.87.27 4 .72M24 20H13V3h11v17m-8-8.5a2.5 2.5 0 0 1 5 0a2.5 2.5 0 0 1-5 0M22 7a2 2 0 0 1-2-2h-3c0 1.11-.89 2-2 2v9a2 2 0 0 1 2 2h3c0-1.1.9-2 2-2V7z" fill="currentColor"/>',
},
'account': {
body: '<path d="M12 4a4 4 0 0 1 4 4a4 4 0 0 1-4 4a4 4 0 0 1-4-4a4 4 0 0 1 4-4m0 10c4.42 0 8 1.79 8 4v2H4v-2c0-2.21 3.58-4 8-4z" fill="currentColor"/>',
},
'home': {
body: '<path d="M10 20v-6h4v6h5v-8h3L12 3L2 12h3v8h5z" fill="currentColor"/>',
},
},
'account-cash': {
body: '<path d="M11 8c0 2.21-1.79 4-4 4s-4-1.79-4-4s1.79-4 4-4s4 1.79 4 4m0 6.72V20H0v-2c0-2.21 3.13-4 7-4c1.5 0 2.87.27 4 .72M24 20H13V3h11v17m-8-8.5a2.5 2.5 0 0 1 5 0a2.5 2.5 0 0 1-5 0M22 7a2 2 0 0 1-2-2h-3c0 1.11-.89 2-2 2v9a2 2 0 0 1 2 2h3c0-1.1.9-2 2-2V7z" fill="currentColor"/>',
},
'account': {
body: '<path d="M12 4a4 4 0 0 1 4 4a4 4 0 0 1-4 4a4 4 0 0 1-4-4a4 4 0 0 1 4-4m0 10c4.42 0 8 1.79 8 4v2H4v-2c0-2.21 3.58-4 8-4z" fill="currentColor"/>',
},
'home': {
body: '<path d="M10 20v-6h4v6h5v-8h3L12 3L2 12h3v8h5z" fill="currentColor"/>',
},
},
width: 24,
height: 24,
width: 24,
height: 24,
});
});
it('Convert placeholders to SVG', () => {

View File

@ -19,24 +19,21 @@ addFinder(iconifyIconFinder);
describe('Scanning DOM', () => {
// Add mentioned icons to storage
const storage = getStorage('', 'mdi');
addIconSet(storage, {
prefix: 'mdi',
icons: {
'account-box': {
body:
'<path d="M6 17c0-2 4-3.1 6-3.1s6 1.1 6 3.1v1H6m9-9a3 3 0 0 1-3 3a3 3 0 0 1-3-3a3 3 0 0 1 3-3a3 3 0 0 1 3 3M3 5v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2z" fill="currentColor"/>',
body: '<path d="M6 17c0-2 4-3.1 6-3.1s6 1.1 6 3.1v1H6m9-9a3 3 0 0 1-3 3a3 3 0 0 1-3-3a3 3 0 0 1 3-3a3 3 0 0 1 3 3M3 5v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2z" fill="currentColor"/>',
},
'account-cash': {
body:
'<path d="M11 8c0 2.21-1.79 4-4 4s-4-1.79-4-4s1.79-4 4-4s4 1.79 4 4m0 6.72V20H0v-2c0-2.21 3.13-4 7-4c1.5 0 2.87.27 4 .72M24 20H13V3h11v17m-8-8.5a2.5 2.5 0 0 1 5 0a2.5 2.5 0 0 1-5 0M22 7a2 2 0 0 1-2-2h-3c0 1.11-.89 2-2 2v9a2 2 0 0 1 2 2h3c0-1.1.9-2 2-2V7z" fill="currentColor"/>',
body: '<path d="M11 8c0 2.21-1.79 4-4 4s-4-1.79-4-4s1.79-4 4-4s4 1.79 4 4m0 6.72V20H0v-2c0-2.21 3.13-4 7-4c1.5 0 2.87.27 4 .72M24 20H13V3h11v17m-8-8.5a2.5 2.5 0 0 1 5 0a2.5 2.5 0 0 1-5 0M22 7a2 2 0 0 1-2-2h-3c0 1.11-.89 2-2 2v9a2 2 0 0 1 2 2h3c0-1.1.9-2 2-2V7z" fill="currentColor"/>',
},
'account': {
body:
'<path d="M12 4a4 4 0 0 1 4 4a4 4 0 0 1-4 4a4 4 0 0 1-4-4a4 4 0 0 1 4-4m0 10c4.42 0 8 1.79 8 4v2H4v-2c0-2.21 3.58-4 8-4z" fill="currentColor"/>',
body: '<path d="M12 4a4 4 0 0 1 4 4a4 4 0 0 1-4 4a4 4 0 0 1-4-4a4 4 0 0 1 4-4m0 10c4.42 0 8 1.79 8 4v2H4v-2c0-2.21 3.58-4 8-4z" fill="currentColor"/>',
},
'home': {
body:
'<path d="M10 20v-6h4v6h5v-8h3L12 3L2 12h3v8h5z" fill="currentColor"/>',
body: '<path d="M10 20v-6h4v6h5v-8h3L12 3L2 12h3v8h5z" fill="currentColor"/>',
},
},
width: 24,

View File

@ -16,35 +16,34 @@ import {
const expect = chai.expect;
// Add finders
addFinder(iconifyFinder);
addFinder(iconifyIconFinder);
describe('Observe DOM', () => {
// Add mentioned icons to storage
const storage = getStorage('', 'mdi');
addIconSet(storage, {
prefix: 'mdi',
icons: {
'account-box': {
body:
'<path d="M6 17c0-2 4-3.1 6-3.1s6 1.1 6 3.1v1H6m9-9a3 3 0 0 1-3 3a3 3 0 0 1-3-3a3 3 0 0 1 3-3a3 3 0 0 1 3 3M3 5v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2z" fill="currentColor"/>',
before(() => {
// Add finders
addFinder(iconifyFinder);
addFinder(iconifyIconFinder);
// Add mentioned icons to storage
addIconSet(storage, {
prefix: 'mdi',
icons: {
'account-box': {
body: '<path d="M6 17c0-2 4-3.1 6-3.1s6 1.1 6 3.1v1H6m9-9a3 3 0 0 1-3 3a3 3 0 0 1-3-3a3 3 0 0 1 3-3a3 3 0 0 1 3 3M3 5v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2z" fill="currentColor"/>',
},
'account-cash': {
body: '<path d="M11 8c0 2.21-1.79 4-4 4s-4-1.79-4-4s1.79-4 4-4s4 1.79 4 4m0 6.72V20H0v-2c0-2.21 3.13-4 7-4c1.5 0 2.87.27 4 .72M24 20H13V3h11v17m-8-8.5a2.5 2.5 0 0 1 5 0a2.5 2.5 0 0 1-5 0M22 7a2 2 0 0 1-2-2h-3c0 1.11-.89 2-2 2v9a2 2 0 0 1 2 2h3c0-1.1.9-2 2-2V7z" fill="currentColor"/>',
},
'account': {
body: '<path d="M12 4a4 4 0 0 1 4 4a4 4 0 0 1-4 4a4 4 0 0 1-4-4a4 4 0 0 1 4-4m0 10c4.42 0 8 1.79 8 4v2H4v-2c0-2.21 3.58-4 8-4z" fill="currentColor"/>',
},
'home': {
body: '<path d="M10 20v-6h4v6h5v-8h3L12 3L2 12h3v8h5z" fill="currentColor"/>',
},
},
'account-cash': {
body:
'<path d="M11 8c0 2.21-1.79 4-4 4s-4-1.79-4-4s1.79-4 4-4s4 1.79 4 4m0 6.72V20H0v-2c0-2.21 3.13-4 7-4c1.5 0 2.87.27 4 .72M24 20H13V3h11v17m-8-8.5a2.5 2.5 0 0 1 5 0a2.5 2.5 0 0 1-5 0M22 7a2 2 0 0 1-2-2h-3c0 1.11-.89 2-2 2v9a2 2 0 0 1 2 2h3c0-1.1.9-2 2-2V7z" fill="currentColor"/>',
},
'account': {
body:
'<path d="M12 4a4 4 0 0 1 4 4a4 4 0 0 1-4 4a4 4 0 0 1-4-4a4 4 0 0 1 4-4m0 10c4.42 0 8 1.79 8 4v2H4v-2c0-2.21 3.58-4 8-4z" fill="currentColor"/>',
},
'home': {
body:
'<path d="M10 20v-6h4v6h5v-8h3L12 3L2 12h3v8h5z" fill="currentColor"/>',
},
},
width: 24,
height: 24,
width: 24,
height: 24,
});
});
it('Basic test', (done) => {

View File

@ -4,10 +4,8 @@ import chai from 'chai';
import { getNode, setRoot } from './node';
import { addFinder } from '@iconify/iconify/lib/modules/finder';
import { FakeData, setFakeData, prepareQuery, sendQuery } from './fake-api';
import { API } from '@iconify/core/lib/api/';
import { setAPIModule } from '@iconify/core/lib/api/modules';
import { setAPIConfig } from '@iconify/core/lib/api/config';
import { coreModules } from '@iconify/core/lib/modules';
import { finder as iconifyFinder } from '@iconify/iconify/lib/finders/iconify';
import { finder as iconifyIconFinder } from '@iconify/iconify/lib/finders/iconify-icon';
import { listRootNodes } from '@iconify/iconify/lib/modules/root';
@ -15,23 +13,24 @@ import { scanDOM, scanElement } from '@iconify/iconify/lib/modules/scanner';
const expect = chai.expect;
// Add finders
addFinder(iconifyFinder);
addFinder(iconifyIconFinder);
// Set API
setAPIModule('', {
prepare: prepareQuery,
send: sendQuery,
});
coreModules.api = API;
let prefixCounter = 0;
function nextPrefix(): string {
return 'scan-dom-api-' + prefixCounter++;
}
describe('Scanning DOM with API', () => {
before(() => {
// Add finders
addFinder(iconifyFinder);
addFinder(iconifyIconFinder);
// Set API
setAPIModule('', {
prepare: prepareQuery,
send: sendQuery,
});
});
it('Scan DOM with API', (done) => {
const provider = nextPrefix();
const prefix1 = nextPrefix();
@ -50,12 +49,10 @@ describe('Scanning DOM with API', () => {
prefix: prefix1,
icons: {
'account-cash': {
body:
'<path d="M11 8c0 2.21-1.79 4-4 4s-4-1.79-4-4s1.79-4 4-4s4 1.79 4 4m0 6.72V20H0v-2c0-2.21 3.13-4 7-4c1.5 0 2.87.27 4 .72M24 20H13V3h11v17m-8-8.5a2.5 2.5 0 0 1 5 0a2.5 2.5 0 0 1-5 0M22 7a2 2 0 0 1-2-2h-3c0 1.11-.89 2-2 2v9a2 2 0 0 1 2 2h3c0-1.1.9-2 2-2V7z" fill="currentColor"/>',
body: '<path d="M11 8c0 2.21-1.79 4-4 4s-4-1.79-4-4s1.79-4 4-4s4 1.79 4 4m0 6.72V20H0v-2c0-2.21 3.13-4 7-4c1.5 0 2.87.27 4 .72M24 20H13V3h11v17m-8-8.5a2.5 2.5 0 0 1 5 0a2.5 2.5 0 0 1-5 0M22 7a2 2 0 0 1-2-2h-3c0 1.11-.89 2-2 2v9a2 2 0 0 1 2 2h3c0-1.1.9-2 2-2V7z" fill="currentColor"/>',
},
'home': {
body:
'<path d="M10 20v-6h4v6h5v-8h3L12 3L2 12h3v8h5z" fill="currentColor"/>',
body: '<path d="M10 20v-6h4v6h5v-8h3L12 3L2 12h3v8h5z" fill="currentColor"/>',
},
},
width: 24,
@ -71,12 +68,10 @@ describe('Scanning DOM with API', () => {
prefix: prefix2,
icons: {
'account-box': {
body:
'<path d="M6 17c0-2 4-3.1 6-3.1s6 1.1 6 3.1v1H6m9-9a3 3 0 0 1-3 3a3 3 0 0 1-3-3a3 3 0 0 1 3-3a3 3 0 0 1 3 3M3 5v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2z" fill="currentColor"/>',
body: '<path d="M6 17c0-2 4-3.1 6-3.1s6 1.1 6 3.1v1H6m9-9a3 3 0 0 1-3 3a3 3 0 0 1-3-3a3 3 0 0 1 3-3a3 3 0 0 1 3 3M3 5v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2z" fill="currentColor"/>',
},
'account': {
body:
'<path d="M12 4a4 4 0 0 1 4 4a4 4 0 0 1-4 4a4 4 0 0 1-4-4a4 4 0 0 1 4-4m0 10c4.42 0 8 1.79 8 4v2H4v-2c0-2.21 3.58-4 8-4z" fill="currentColor"/>',
body: '<path d="M12 4a4 4 0 0 1 4 4a4 4 0 0 1-4 4a4 4 0 0 1-4-4a4 4 0 0 1 4-4m0 10c4.42 0 8 1.79 8 4v2H4v-2c0-2.21 3.58-4 8-4z" fill="currentColor"/>',
},
},
width: 24,
@ -163,12 +158,10 @@ describe('Scanning DOM with API', () => {
prefix: prefix1,
icons: {
'account-cash': {
body:
'<path d="M11 8c0 2.21-1.79 4-4 4s-4-1.79-4-4s1.79-4 4-4s4 1.79 4 4m0 6.72V20H0v-2c0-2.21 3.13-4 7-4c1.5 0 2.87.27 4 .72M24 20H13V3h11v17m-8-8.5a2.5 2.5 0 0 1 5 0a2.5 2.5 0 0 1-5 0M22 7a2 2 0 0 1-2-2h-3c0 1.11-.89 2-2 2v9a2 2 0 0 1 2 2h3c0-1.1.9-2 2-2V7z" fill="currentColor"/>',
body: '<path d="M11 8c0 2.21-1.79 4-4 4s-4-1.79-4-4s1.79-4 4-4s4 1.79 4 4m0 6.72V20H0v-2c0-2.21 3.13-4 7-4c1.5 0 2.87.27 4 .72M24 20H13V3h11v17m-8-8.5a2.5 2.5 0 0 1 5 0a2.5 2.5 0 0 1-5 0M22 7a2 2 0 0 1-2-2h-3c0 1.11-.89 2-2 2v9a2 2 0 0 1 2 2h3c0-1.1.9-2 2-2V7z" fill="currentColor"/>',
},
'home': {
body:
'<path d="M10 20v-6h4v6h5v-8h3L12 3L2 12h3v8h5z" fill="currentColor"/>',
body: '<path d="M10 20v-6h4v6h5v-8h3L12 3L2 12h3v8h5z" fill="currentColor"/>',
},
},
width: 24,
@ -184,12 +177,10 @@ describe('Scanning DOM with API', () => {
prefix: prefix2,
icons: {
'account-box': {
body:
'<path d="M6 17c0-2 4-3.1 6-3.1s6 1.1 6 3.1v1H6m9-9a3 3 0 0 1-3 3a3 3 0 0 1-3-3a3 3 0 0 1 3-3a3 3 0 0 1 3 3M3 5v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2z" fill="currentColor"/>',
body: '<path d="M6 17c0-2 4-3.1 6-3.1s6 1.1 6 3.1v1H6m9-9a3 3 0 0 1-3 3a3 3 0 0 1-3-3a3 3 0 0 1 3-3a3 3 0 0 1 3 3M3 5v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2z" fill="currentColor"/>',
},
'account': {
body:
'<path d="M12 4a4 4 0 0 1 4 4a4 4 0 0 1-4 4a4 4 0 0 1-4-4a4 4 0 0 1 4-4m0 10c4.42 0 8 1.79 8 4v2H4v-2c0-2.21 3.58-4 8-4z" fill="currentColor"/>',
body: '<path d="M12 4a4 4 0 0 1 4 4a4 4 0 0 1-4 4a4 4 0 0 1-4-4a4 4 0 0 1 4-4m0 10c4.42 0 8 1.79 8 4v2H4v-2c0-2.21 3.58-4 8-4z" fill="currentColor"/>',
},
},
width: 24,
@ -205,12 +196,10 @@ describe('Scanning DOM with API', () => {
prefix: prefix1,
icons: {
'account-box': {
body:
'<path d="M6 17c0-2 4-3.1 6-3.1s6 1.1 6 3.1v1H6m9-9a3 3 0 0 1-3 3a3 3 0 0 1-3-3a3 3 0 0 1 3-3a3 3 0 0 1 3 3M3 5v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2z" fill="currentColor"/>',
body: '<path d="M6 17c0-2 4-3.1 6-3.1s6 1.1 6 3.1v1H6m9-9a3 3 0 0 1-3 3a3 3 0 0 1-3-3a3 3 0 0 1 3-3a3 3 0 0 1 3 3M3 5v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2z" fill="currentColor"/>',
},
'account': {
body:
'<path d="M12 4a4 4 0 0 1 4 4a4 4 0 0 1-4 4a4 4 0 0 1-4-4a4 4 0 0 1 4-4m0 10c4.42 0 8 1.79 8 4v2H4v-2c0-2.21 3.58-4 8-4z" fill="currentColor"/>',
body: '<path d="M12 4a4 4 0 0 1 4 4a4 4 0 0 1-4 4a4 4 0 0 1-4-4a4 4 0 0 1 4-4m0 10c4.42 0 8 1.79 8 4v2H4v-2c0-2.21 3.58-4 8-4z" fill="currentColor"/>',
},
},
width: 24,
@ -318,12 +307,10 @@ describe('Scanning DOM with API', () => {
prefix: prefix1,
icons: {
'account-cash': {
body:
'<path d="M11 8c0 2.21-1.79 4-4 4s-4-1.79-4-4s1.79-4 4-4s4 1.79 4 4m0 6.72V20H0v-2c0-2.21 3.13-4 7-4c1.5 0 2.87.27 4 .72M24 20H13V3h11v17m-8-8.5a2.5 2.5 0 0 1 5 0a2.5 2.5 0 0 1-5 0M22 7a2 2 0 0 1-2-2h-3c0 1.11-.89 2-2 2v9a2 2 0 0 1 2 2h3c0-1.1.9-2 2-2V7z" fill="currentColor"/>',
body: '<path d="M11 8c0 2.21-1.79 4-4 4s-4-1.79-4-4s1.79-4 4-4s4 1.79 4 4m0 6.72V20H0v-2c0-2.21 3.13-4 7-4c1.5 0 2.87.27 4 .72M24 20H13V3h11v17m-8-8.5a2.5 2.5 0 0 1 5 0a2.5 2.5 0 0 1-5 0M22 7a2 2 0 0 1-2-2h-3c0 1.11-.89 2-2 2v9a2 2 0 0 1 2 2h3c0-1.1.9-2 2-2V7z" fill="currentColor"/>',
},
'home': {
body:
'<path d="M10 20v-6h4v6h5v-8h3L12 3L2 12h3v8h5z" fill="currentColor"/>',
body: '<path d="M10 20v-6h4v6h5v-8h3L12 3L2 12h3v8h5z" fill="currentColor"/>',
},
},
width: 24,
@ -339,12 +326,10 @@ describe('Scanning DOM with API', () => {
prefix: prefix2,
icons: {
'account-box': {
body:
'<path d="M6 17c0-2 4-3.1 6-3.1s6 1.1 6 3.1v1H6m9-9a3 3 0 0 1-3 3a3 3 0 0 1-3-3a3 3 0 0 1 3-3a3 3 0 0 1 3 3M3 5v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2z" fill="currentColor"/>',
body: '<path d="M6 17c0-2 4-3.1 6-3.1s6 1.1 6 3.1v1H6m9-9a3 3 0 0 1-3 3a3 3 0 0 1-3-3a3 3 0 0 1 3-3a3 3 0 0 1 3 3M3 5v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2z" fill="currentColor"/>',
},
'account': {
body:
'<path d="M12 4a4 4 0 0 1 4 4a4 4 0 0 1-4 4a4 4 0 0 1-4-4a4 4 0 0 1 4-4m0 10c4.42 0 8 1.79 8 4v2H4v-2c0-2.21 3.58-4 8-4z" fill="currentColor"/>',
body: '<path d="M12 4a4 4 0 0 1 4 4a4 4 0 0 1-4 4a4 4 0 0 1-4-4a4 4 0 0 1 4-4m0 10c4.42 0 8 1.79 8 4v2H4v-2c0-2.21 3.58-4 8-4z" fill="currentColor"/>',
},
},
width: 24,
@ -423,8 +408,7 @@ describe('Scanning DOM with API', () => {
prefix,
icons: {
home: {
body:
'<path d="M10 20v-6h4v6h5v-8h3L12 3L2 12h3v8h5z" fill="currentColor"/>',
body: '<path d="M10 20v-6h4v6h5v-8h3L12 3L2 12h3v8h5z" fill="currentColor"/>',
},
},
width: 24,

View File

@ -1,7 +1,8 @@
import { PendingQueryItem } from '@cyberalien/redundancy';
import {
APIQueryParams,
IconifyAPIPrepareQuery,
IconifyAPIIconsQueryParams,
IconifyAPIQueryParams,
IconifyAPIPrepareIconsQuery,
IconifyAPISendQuery,
} from '@iconify/core/lib/api/modules';
import { IconifyJSON } from '@iconify/types';
@ -38,20 +39,20 @@ export function setFakeData(
providerFakeData[prefix].push(item);
}
interface FakeAPIQueryParams extends APIQueryParams {
interface FakeAPIQueryParams extends IconifyAPIIconsQueryParams {
data: FakeData;
}
/**
* Prepare params
*/
export const prepareQuery: IconifyAPIPrepareQuery = (
export const prepareQuery: IconifyAPIPrepareIconsQuery = (
provider: string,
prefix: string,
icons: string[]
): APIQueryParams[] => {
): IconifyAPIIconsQueryParams[] => {
// Find items that have query
const items: APIQueryParams[] = [];
const items: IconifyAPIIconsQueryParams[] = [];
let missing = icons.slice(0);
if (fakeData[provider] === void 0) {
@ -59,6 +60,7 @@ export const prepareQuery: IconifyAPIPrepareQuery = (
}
const providerFakeData = fakeData[provider];
const type = 'icons';
if (providerFakeData[prefix] !== void 0) {
providerFakeData[prefix].forEach((item) => {
const matches = item.icons.filter(
@ -72,6 +74,7 @@ export const prepareQuery: IconifyAPIPrepareQuery = (
// Contains at least one matching icon
missing = missing.filter((icon) => matches.indexOf(icon) === -1);
const query: FakeAPIQueryParams = {
type,
provider,
prefix,
icons: matches,
@ -89,9 +92,15 @@ export const prepareQuery: IconifyAPIPrepareQuery = (
*/
export const sendQuery: IconifyAPISendQuery = (
host: string,
params: APIQueryParams,
params: IconifyAPIQueryParams,
status: PendingQueryItem
): void => {
if (params.type !== 'icons') {
// Fake API supports only icons
status.done(void 0, 400);
return;
}
const provider = params.provider;
const prefix = params.prefix;
const icons = params.icons;

View File

@ -2,7 +2,7 @@
"name": "@iconify/core",
"description": "Reusable files used by multiple Iconify packages",
"author": "Vjacheslav Trushkin <cyberalien@gmail.com> (https://iconify.design)",
"version": "1.1.3",
"version": "1.2.0",
"license": "(Apache-2.0 OR GPL-2.0)",
"bugs": "https://github.com/iconify/iconify/issues",
"homepage": "https://iconify.design/",

View File

@ -1,7 +1,7 @@
import type {
IconifyIconLoaderCallback,
IconifyIconLoaderAbort,
} from '../interfaces/loader';
} from './icons';
import { getStorage } from '../storage/storage';
import type { SortedIcons } from '../icon/sort';
import type { IconifyIconSource } from '@iconify/utils/lib/icon/name';
@ -25,10 +25,13 @@ interface CallbackItem {
// Records sorted by provider and prefix
// This export is only for unit testing, should not be used
export const callbacks: Record<string, Record<string, CallbackItem[]>> =
Object.create(null);
const pendingUpdates: Record<string, Record<string, boolean>> =
Object.create(null);
export const callbacks: Record<
string,
Record<string, CallbackItem[]>
> = Object.create(null);
const pendingUpdates: Record<string, Record<string, boolean>> = Object.create(
null
);
/**
* Remove callback

View File

@ -16,7 +16,7 @@ export type PartialIconifyAPIConfig = Partial<IconifyAPIConfig>;
/**
* Create full API configuration from partial data
*/
function createConfig(
export function createAPIConfig(
source: PartialIconifyAPIConfig
): IconifyAPIConfig | null {
let resources;
@ -99,7 +99,7 @@ while (fallBackAPISources.length > 0) {
}
// Add default API
configStorage[''] = createConfig({
configStorage[''] = createAPIConfig({
resources: ['https://api.iconify.design'].concat(fallBackAPI),
}) as IconifyAPIConfig;
@ -110,7 +110,7 @@ export function setAPIConfig(
provider: string,
customConfig: PartialIconifyAPIConfig
): boolean {
const config = createConfig(customConfig);
const config = createAPIConfig(customConfig);
if (config === null) {
return false;
}
@ -126,9 +126,9 @@ export type GetAPIConfig = (provider: string) => IconifyAPIConfig | undefined;
/**
* Get API configuration
*/
export const getAPIConfig: GetAPIConfig = (
provider: string
): IconifyAPIConfig | undefined => configStorage[provider];
export function getAPIConfig(provider: string): IconifyAPIConfig | undefined {
return configStorage[provider];
}
/**
* List API providers

View File

@ -1,19 +1,28 @@
import { API } from '.';
import type { IconifyIconName } from '@iconify/utils/lib/icon/name';
import { sendAPIQuery } from './query';
import { loadIcons } from './icons';
import type {
IconifyIconLoaderAbort,
IconifyIconLoaderCallback,
} from '../interfaces/loader';
import type { GetAPIConfig, IconifyAPIConfig } from './config';
} from './icons';
import type {
GetAPIConfig,
IconifyAPIConfig,
PartialIconifyAPIConfig,
} from './config';
import { getAPIConfig, setAPIConfig } from './config';
import type {
IconifyAPIModule,
IconifyAPIQueryParams,
IconifyAPICustomQueryParams,
} from './modules';
import { setAPIModule, getAPIModule } from './modules';
import { setAPIModule } from './modules';
import type { MergeParams, IconifyAPIMergeQueryParams } from './params';
import { mergeParams } from './params';
import type {
QueryAbortCallback,
QueryDoneCallback,
} from '@cyberalien/redundancy';
/**
* Iconify API functions
@ -37,7 +46,7 @@ export interface IconifyAPIFunctions {
}
export const APIFunctions: IconifyAPIFunctions = {
loadIcons: API.loadIcons,
loadIcons,
addAPIProvider: setAPIConfig,
};
@ -55,14 +64,18 @@ export interface IconifyAPIInternalFunctions {
getAPIConfig: GetAPIConfig;
/**
* Set API module
* Set custom API module
*/
setAPIModule: (provider: string, item: IconifyAPIModule) => void;
/**
* Get API module
* Send API query
*/
getAPIModule: (provider: string) => IconifyAPIModule | undefined;
sendAPIQuery: (
target: string | PartialIconifyAPIConfig,
query: IconifyAPIQueryParams,
callback: QueryDoneCallback
) => QueryAbortCallback;
/**
* Optional setFetch and getFetch (should be imported from ./modules/fetch if fetch is used)
@ -79,7 +92,7 @@ export interface IconifyAPIInternalFunctions {
export const APIInternalFunctions: IconifyAPIInternalFunctions = {
getAPIConfig,
setAPIModule,
getAPIModule,
sendAPIQuery,
mergeParams,
};

View File

@ -1,32 +1,53 @@
import type { Redundancy, QueryModuleCallback } from '@cyberalien/redundancy';
import type { IconifyJSON } from '@iconify/types';
import { initRedundancy } from '@cyberalien/redundancy';
import type { SortedIcons } from '../icon/sort';
import { sortIcons } from '../icon/sort';
import type {
IconifyIconLoaderAbort,
IconifyIconLoaderCallback,
IconifyLoadIcons,
} from '../interfaces/loader';
import type { IsPending, IconifyAPI } from '../interfaces/api';
import { storeCallback, updateCallbacks } from './callbacks';
import { getAPIModule } from './modules';
import type { IconifyAPIConfig } from './config';
import { getAPIConfig } from './config';
import { getStorage, addIconSet } from '../storage/storage';
import { coreModules } from '../modules';
import type {
IconifyIconName,
IconifyIconSource,
} from '@iconify/utils/lib/icon/name';
import { listToIcons } from '../icon/list';
import { allowSimpleNames } from '../storage/functions';
import { sendAPIQuery } from './query';
import { cache } from '../cache';
// Empty abort callback for loadIcons()
function emptyCallback(): void {
// Do nothing
}
/**
* Function to abort loading (usually just removes callback because loading is already in progress)
*/
export type IconifyIconLoaderAbort = () => void;
/**
* Loader callback
*
* Provides list of icons that have been loaded
*/
export type IconifyIconLoaderCallback = (
loaded: IconifyIconName[],
missing: IconifyIconName[],
pending: IconifyIconName[],
unsubscribe: IconifyIconLoaderAbort
) => void;
/**
* Function to load icons
*/
export type IconifyLoadIcons = (
icons: (IconifyIconName | string)[],
callback?: IconifyIconLoaderCallback
) => IconifyIconLoaderAbort;
/**
* Function to check if icon is pending
*/
export type IsPending = (icon: IconifyIconName) => boolean;
/**
* List of icons that are being loaded.
*
@ -63,38 +84,6 @@ const loaderFlags: Record<string, Record<string, boolean>> = Object.create(
);
const queueFlags: Record<string, Record<string, boolean>> = Object.create(null);
// Redundancy instances cache, sorted by provider
interface IconifyAPIInternalStorage {
config: IconifyAPIConfig;
redundancy: Redundancy;
}
const redundancyCache: Record<string, IconifyAPIInternalStorage> =
Object.create(null);
/**
* Get Redundancy instance for provider
*/
function getRedundancyCache(
provider: string
): IconifyAPIInternalStorage | undefined {
if (redundancyCache[provider] === void 0) {
const config = getAPIConfig(provider);
if (!config) {
// No way to load icons because configuration is not set!
return;
}
const redundancy = initRedundancy(config);
const cachedReundancy = {
config,
redundancy,
};
redundancyCache[provider] = cachedReundancy;
}
return redundancyCache[provider];
}
/**
* Function called when new icons have been loaded
*/
@ -158,9 +147,6 @@ function loadNewIcons(provider: string, prefix: string, icons: string[]): void {
.sort();
}
// Redundancy item
let cachedReundancy: IconifyAPIInternalStorage;
// Trigger update on next tick, mering multiple synchronous requests into one asynchronous request
if (!providerQueueFlags[prefix]) {
providerQueueFlags[prefix] = true;
@ -179,72 +165,54 @@ function loadNewIcons(provider: string, prefix: string, icons: string[]): void {
return;
}
// Get API config and Redundancy instance
if (cachedReundancy === void 0) {
const redundancy = getRedundancyCache(provider);
if (redundancy === void 0) {
// No way to load icons because configuration is not set!
err();
return;
}
cachedReundancy = redundancy;
}
// Prepare parameters and run queries
const params = api.prepare(provider, prefix, icons);
params.forEach((item) => {
cachedReundancy.redundancy.query(
item,
api.send as QueryModuleCallback,
(data, error) => {
const storage = getStorage(provider, prefix);
sendAPIQuery(provider, item, (data, error) => {
const storage = getStorage(provider, prefix);
// Check for error
if (typeof data !== 'object') {
if (error !== 404) {
// Do not handle error unless it is 404
// Check for error
if (typeof data !== 'object') {
if (error !== 404) {
// Do not handle error unless it is 404
return;
}
// Not found: mark as missing
const t = Date.now();
item.icons.forEach((name) => {
storage.missing[name] = t;
});
} else {
// Add icons to storage
try {
const added = addIconSet(
storage,
data as IconifyJSON,
'all'
);
if (typeof added === 'boolean') {
return;
}
// Not found: mark as missing
const t = Date.now();
item.icons.forEach((name) => {
storage.missing[name] = t;
// Remove added icons from pending list
const pending = providerPendingIcons[prefix];
added.forEach((name) => {
delete pending[name];
});
} else {
// Add icons to storage
try {
const added = addIconSet(
storage,
data as IconifyJSON,
'all'
);
if (typeof added === 'boolean') {
return;
}
// Remove added icons from pending list
const pending = providerPendingIcons[prefix];
added.forEach((name) => {
delete pending[name];
});
// Cache API response
if (coreModules.cache) {
coreModules.cache(
provider,
data as IconifyJSON
);
}
} catch (err) {
console.error(err);
// Cache API response
if (cache.store) {
cache.store(provider, data as IconifyJSON);
}
} catch (err) {
console.error(err);
}
// Trigger update on next tick
loadedNewIcons(provider, prefix);
}
);
// Trigger update on next tick
loadedNewIcons(provider, prefix);
});
});
});
}
@ -253,18 +221,20 @@ function loadNewIcons(provider: string, prefix: string, icons: string[]): void {
/**
* Check if icon is being loaded
*/
const isPending: IsPending = (icon: IconifyIconName): boolean => {
export const isPending: IsPending = (icon: IconifyIconName): boolean => {
const provider = icon.provider;
const prefix = icon.prefix;
return (
pendingIcons[icon.provider] !== void 0 &&
pendingIcons[icon.provider][icon.prefix] !== void 0 &&
pendingIcons[icon.provider][icon.prefix][icon.name] !== void 0
pendingIcons[provider] &&
pendingIcons[provider][prefix] &&
pendingIcons[provider][prefix][icon.name] !== void 0
);
};
/**
* Load icons
*/
const loadIcons: IconifyLoadIcons = (
export const loadIcons: IconifyLoadIcons = (
icons: (IconifyIconName | string)[],
callback?: IconifyIconLoaderCallback
): IconifyIconLoaderAbort => {
@ -369,11 +339,3 @@ const loadIcons: IconifyLoadIcons = (
? storeCallback(callback, sortedIcons, sources)
: emptyCallback;
};
/**
* Export module
*/
export const API: IconifyAPI = {
isPending,
loadIcons,
};

View File

@ -1,5 +1,4 @@
import type { PendingQueryItem } from '@cyberalien/redundancy';
import type { GetAPIConfig } from '../api/config';
/**
* Params for sendQuery()
@ -12,7 +11,7 @@ export interface IconifyAPIIconsQueryParams {
}
export interface IconifyAPICustomQueryParams {
type: 'custom';
provider: string;
provider?: string; // Provider is optional. If missing, temporary config is created based on host
uri: string;
}
@ -59,12 +58,5 @@ export function setAPIModule(provider: string, item: IconifyAPIModule): void {
* Get API module
*/
export function getAPIModule(provider: string): IconifyAPIModule | undefined {
return storage[provider] === void 0 ? storage[''] : storage[provider];
return storage[provider] || storage[''];
}
/**
* Function to return API interface
*/
export type GetIconifyAPIModule = (
getAPIConfig: GetAPIConfig
) => IconifyAPIModule;

View File

@ -4,10 +4,9 @@ import type {
IconifyAPIPrepareIconsQuery,
IconifyAPISendQuery,
IconifyAPIModule,
GetIconifyAPIModule,
IconifyAPIIconsQueryParams,
} from '../modules';
import type { GetAPIConfig } from '../config';
import { getAPIConfig } from '../config';
import { mergeParams } from '../params';
/**
@ -71,166 +70,190 @@ export function getFetch(): typeof fetchModule {
}
/**
* Return API module
* Calculate maximum icons list length for prefix
*/
export const getAPIModule: GetIconifyAPIModule = (
getAPIConfig: GetAPIConfig
): IconifyAPIModule => {
/**
* Calculate maximum icons list length for prefix
*/
function calculateMaxLength(provider: string, prefix: string): number {
// Get config and store path
const config = getAPIConfig(provider);
if (!config) {
return 0;
}
// Calculate
let result;
if (!config.maxURL) {
result = 0;
} else {
let maxHostLength = 0;
config.resources.forEach((item) => {
const host = item as string;
maxHostLength = Math.max(maxHostLength, host.length);
});
// Get available length
const url = mergeParams(prefix + '.json', {
icons: '',
});
result =
config.maxURL - maxHostLength - config.path.length - url.length;
}
// Cache stuff and return result
const cacheKey = provider + ':' + prefix;
pathCache[provider] = config.path;
maxLengthCache[cacheKey] = result;
return result;
function calculateMaxLength(provider: string, prefix: string): number {
// Get config and store path
const config = getAPIConfig(provider);
if (!config) {
return 0;
}
/**
* Prepare params
*/
const prepare: IconifyAPIPrepareIconsQuery = (
provider: string,
prefix: string,
icons: string[]
): IconifyAPIIconsQueryParams[] => {
const results: IconifyAPIIconsQueryParams[] = [];
// Get maximum icons list length
let maxLength = maxLengthCache[prefix];
if (maxLength === void 0) {
maxLength = calculateMaxLength(provider, prefix);
}
// Split icons
const type = 'icons';
let item: IconifyAPIIconsQueryParams = {
type,
provider,
prefix,
icons: [],
};
let length = 0;
icons.forEach((name, index) => {
length += name.length + 1;
if (length >= maxLength && index > 0) {
// Next set
results.push(item);
item = {
type,
provider,
prefix,
icons: [],
};
length = name.length;
}
item.icons.push(name);
// Calculate
let result;
if (!config.maxURL) {
result = 0;
} else {
let maxHostLength = 0;
config.resources.forEach((item) => {
const host = item as string;
maxHostLength = Math.max(maxHostLength, host.length);
});
results.push(item);
return results;
// Get available length
const url = mergeParams(prefix + '.json', {
icons: '',
});
result =
config.maxURL - maxHostLength - config.path.length - url.length;
}
// Cache stuff and return result
const cacheKey = provider + ':' + prefix;
pathCache[provider] = config.path;
maxLengthCache[cacheKey] = result;
return result;
}
/**
* Prepare params
*/
const prepare: IconifyAPIPrepareIconsQuery = (
provider: string,
prefix: string,
icons: string[]
): IconifyAPIIconsQueryParams[] => {
const results: IconifyAPIIconsQueryParams[] = [];
// Get maximum icons list length
let maxLength = maxLengthCache[prefix];
if (maxLength === void 0) {
maxLength = calculateMaxLength(provider, prefix);
}
// Split icons
const type = 'icons';
let item: IconifyAPIIconsQueryParams = {
type,
provider,
prefix,
icons: [],
};
/**
* Load icons
*/
const send: IconifyAPISendQuery = (
host: string,
params: IconifyAPIQueryParams,
status: PendingQueryItem
): void => {
const provider = params.provider;
let path: string;
switch (params.type) {
case 'icons': {
const prefix = params.prefix;
const icons = params.icons;
const iconsList = icons.join(',');
path =
pathCache[provider] +
mergeParams(prefix + '.json', {
icons: iconsList,
});
break;
}
case 'custom': {
const uri = params.uri;
path =
pathCache[provider] +
(uri.slice(0, 1) === '/' ? uri.slice(1) : uri);
break;
}
default:
// Fail: return 400 Bad Request
status.done(void 0, 400);
return;
let length = 0;
icons.forEach((name, index) => {
length += name.length + 1;
if (length >= maxLength && index > 0) {
// Next set
results.push(item);
item = {
type,
provider,
prefix,
icons: [],
};
length = name.length;
}
if (!fetchModule) {
// Fail: return 424 Failed Dependency (its not meant to be used like that, but it is the best match)
status.done(void 0, 424);
return;
}
item.icons.push(name);
});
results.push(item);
// console.log('API query:', host + path);
fetchModule(host + path)
.then((response) => {
if (response.status !== 200) {
status.done(void 0, response.status);
return;
}
return response.json();
})
.then((data) => {
if (typeof data !== 'object' || data === null) {
return;
}
// Store cache and complete
status.done(data);
})
.catch((err) => {
// Error
status.done(void 0, err.errno);
});
};
// Return functions
return {
prepare,
send,
};
return results;
};
/**
* Get path
*/
function getPath(provider?: string): string {
if (typeof provider === 'string') {
if (pathCache[provider] === void 0) {
const config = getAPIConfig(provider);
if (!config) {
return '/';
}
pathCache[provider] = config.path;
}
return pathCache[provider];
}
// No provider config, assume path is '/'
return '/';
}
/**
* Load icons
*/
const send: IconifyAPISendQuery = (
host: string,
params: IconifyAPIQueryParams,
status: PendingQueryItem
): void => {
if (!fetchModule) {
// Fail: return "424 Failed Dependency" (its not meant to be used like that, but it is the closest match)
status.done(void 0, 424);
return;
}
// Get path
let path = getPath(params.provider);
switch (params.type) {
case 'icons': {
const prefix = params.prefix;
const icons = params.icons;
const iconsList = icons.join(',');
path += mergeParams(prefix + '.json', {
icons: iconsList,
});
break;
}
case 'custom': {
const uri = params.uri;
path += uri.slice(0, 1) === '/' ? uri.slice(1) : uri;
break;
}
default:
// Fail: return 400 Bad Request
status.done(void 0, 400);
return;
}
// Error code to return if fetch throws an error: "503 Service Unavailable"
let defaultError = 503;
// console.log('API query:', host + path);
fetchModule(host + path)
.then((response) => {
if (response.status !== 200) {
setTimeout(() => {
// Complete on next tick to get out of try...catch
status.done(void 0, response.status);
});
return;
}
// Parse JSON, fail with "501 Not Implemented" if response cannot be decoded
defaultError = 501;
return response.json();
})
.then((data) => {
if (typeof data !== 'object' || data === null) {
setTimeout(() => {
// Complete on next tick to get out of try...catch
status.done(void 0, defaultError);
});
return;
}
// Store cache and complete on next tick
setTimeout(() => {
// Complete on next tick to get out of try...catch
status.done(data);
});
})
.catch(() => {
status.done(void 0, defaultError);
});
};
/**
* Export module
*/
export const fetchAPIModule: IconifyAPIModule = {
prepare,
send,
};

View File

@ -5,10 +5,9 @@ import type {
IconifyAPIPrepareIconsQuery,
IconifyAPISendQuery,
IconifyAPIModule,
GetIconifyAPIModule,
IconifyAPIIconsQueryParams,
} from '../modules';
import type { GetAPIConfig } from '../config';
import { getAPIConfig } from '../config';
import { mergeParams } from '../params';
/**
@ -80,160 +79,152 @@ function getGlobal(): JSONPRoot {
}
/**
* Return API module
* Calculate maximum icons list length for prefix
*/
export const getAPIModule: GetIconifyAPIModule = (
getAPIConfig: GetAPIConfig
): IconifyAPIModule => {
/**
* Calculate maximum icons list length for prefix
*/
function calculateMaxLength(provider: string, prefix: string): number {
// Get config and store path
const config = getAPIConfig(provider);
if (!config) {
return 0;
}
// Calculate
let result;
if (!config.maxURL) {
result = 0;
} else {
let maxHostLength = 0;
config.resources.forEach((item) => {
const host = item as string;
maxHostLength = Math.max(maxHostLength, host.length);
});
// Make sure global is set
getGlobal();
// Get available length
const url = mergeParams(prefix + '.js', {
icons: '',
callback: rootVarName!,
});
result =
config.maxURL - maxHostLength - config.path.length - url.length;
}
// Cache stuff and return result
const cacheKey = provider + ':' + prefix;
pathCache[cacheKey] = config.path;
maxLengthCache[cacheKey] = result;
return result;
function calculateMaxLength(provider: string, prefix: string): number {
// Get config and store path
const config = getAPIConfig(provider);
if (!config) {
return 0;
}
/**
* Prepare params
*/
const prepare: IconifyAPIPrepareIconsQuery = (
provider: string,
prefix: string,
icons: string[]
): IconifyAPIIconsQueryParams[] => {
const results: IconifyAPIIconsQueryParams[] = [];
// Get maximum icons list length
const cacheKey = provider + ':' + prefix;
let maxLength = maxLengthCache[cacheKey];
if (maxLength === void 0) {
maxLength = calculateMaxLength(provider, prefix);
}
// Split icons
const type = 'icons';
let item: IconifyAPIIconsQueryParams = {
type,
provider,
prefix,
icons: [],
};
let length = 0;
icons.forEach((name, index) => {
length += name.length + 1;
if (length >= maxLength && index > 0) {
// Next set
results.push(item);
item = {
type,
provider,
prefix,
icons: [],
};
length = name.length;
}
item.icons.push(name);
// Calculate
let result;
if (!config.maxURL) {
result = 0;
} else {
let maxHostLength = 0;
config.resources.forEach((item) => {
const host = item as string;
maxHostLength = Math.max(maxHostLength, host.length);
});
results.push(item);
return results;
};
/**
* Load icons
*/
const send: IconifyAPISendQuery = (
host: string,
params: IconifyAPIQueryParams,
status: PendingQueryItem
): void => {
if (params.type !== 'icons') {
// JSONP supports only icons
status.done(void 0, 400);
return;
}
const provider = params.provider;
const prefix = params.prefix;
const icons = params.icons;
const iconsList = icons.join(',');
const cacheKey = provider + ':' + prefix;
// Create callback prefix
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const cbPrefix = prefix.split('-').shift()!.slice(0, 3);
const global = getGlobal();
// Callback hash
let cbCounter = hash(
provider + ':' + host + ':' + prefix + ':' + iconsList
);
while (global[cbPrefix + cbCounter] !== void 0) {
cbCounter++;
}
const callbackName = cbPrefix + cbCounter;
// Make sure global is set
getGlobal();
// Get available length
const url = mergeParams(prefix + '.js', {
icons: iconsList,
callback: rootVarName!.replace('{cb}', callbackName),
icons: '',
callback: rootVarName!,
});
const path = pathCache[cacheKey] + url;
result =
config.maxURL - maxHostLength - config.path.length - url.length;
}
global[callbackName] = (data: unknown): void => {
// Remove callback and complete query
delete global[callbackName];
status.done(data);
};
// Cache stuff and return result
const cacheKey = provider + ':' + prefix;
pathCache[cacheKey] = config.path;
maxLengthCache[cacheKey] = result;
return result;
}
// Create URI
const uri = host + path;
// console.log('API query:', uri);
/**
* Prepare params
*/
const prepare: IconifyAPIPrepareIconsQuery = (
provider: string,
prefix: string,
icons: string[]
): IconifyAPIIconsQueryParams[] => {
const results: IconifyAPIIconsQueryParams[] = [];
// Create script and append it to head
const script = document.createElement('script');
script.type = 'text/javascript';
script.async = true;
script.src = uri;
document.head.appendChild(script);
// Get maximum icons list length
const cacheKey = provider + ':' + prefix;
let maxLength = maxLengthCache[cacheKey];
if (maxLength === void 0) {
maxLength = calculateMaxLength(provider, prefix);
}
// Split icons
const type = 'icons';
let item: IconifyAPIIconsQueryParams = {
type,
provider,
prefix,
icons: [],
};
let length = 0;
icons.forEach((name, index) => {
length += name.length + 1;
if (length >= maxLength && index > 0) {
// Next set
results.push(item);
item = {
type,
provider,
prefix,
icons: [],
};
length = name.length;
}
// Return functions
return {
prepare,
send,
};
item.icons.push(name);
});
results.push(item);
return results;
};
/**
* Load icons
*/
const send: IconifyAPISendQuery = (
host: string,
params: IconifyAPIQueryParams,
status: PendingQueryItem
): void => {
if (params.type !== 'icons') {
// JSONP supports only icons
status.done(void 0, 400);
return;
}
const provider = params.provider;
const prefix = params.prefix;
const icons = params.icons;
const iconsList = icons.join(',');
const cacheKey = provider + ':' + prefix;
// Create callback prefix
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const cbPrefix = prefix.split('-').shift()!.slice(0, 3);
const global = getGlobal();
// Callback hash
let cbCounter = hash(
provider + ':' + host + ':' + prefix + ':' + iconsList
);
while (global[cbPrefix + cbCounter] !== void 0) {
cbCounter++;
}
const callbackName = cbPrefix + cbCounter;
const url = mergeParams(prefix + '.js', {
icons: iconsList,
callback: rootVarName!.replace('{cb}', callbackName),
});
const path = pathCache[cacheKey] + url;
global[callbackName] = (data: unknown): void => {
// Remove callback and complete query
delete global[callbackName];
status.done(data);
};
// Create URI
const uri = host + path;
// console.log('API query:', uri);
// Create script and append it to head
const script = document.createElement('script');
script.type = 'text/javascript';
script.async = true;
script.src = uri;
document.head.appendChild(script);
};
/**
* Return API module
*/
export const jsonpAPIModule: IconifyAPIModule = { prepare, send };

View File

@ -127,10 +127,7 @@ export const mockAPIModule: IconifyAPIModule = {
): IconifyAPIIconsQueryParams[] => {
const type = 'icons';
if (
iconsStorage[provider] === void 0 ||
iconsStorage[provider][prefix] === void 0
) {
if (!iconsStorage[provider] || !iconsStorage[provider][prefix]) {
// No mock data: bundle all icons in one request that will return 404
return [
{
@ -223,6 +220,12 @@ export const mockAPIModule: IconifyAPIModule = {
status: PendingQueryItem
) => {
const provider = params.provider;
if (provider === void 0) {
// Fail: return 400 Bad Request
status.done(void 0, 400);
return;
}
let data: IconifyMockAPI;
switch (params.type) {

View File

@ -0,0 +1,106 @@
import type {
Redundancy,
QueryDoneCallback,
QueryAbortCallback,
QueryModuleCallback,
} from '@cyberalien/redundancy';
import { initRedundancy } from '@cyberalien/redundancy';
import {
getAPIModule,
IconifyAPIQueryParams,
IconifyAPISendQuery,
} from './modules';
import {
createAPIConfig,
IconifyAPIConfig,
PartialIconifyAPIConfig,
} from './config';
import { getAPIConfig } from './config';
// Empty abort callback
function emptyCallback(): void {
// Do nothing
}
// Redundancy instances cache, sorted by provider
interface IconifyAPIInternalStorage {
config: IconifyAPIConfig;
redundancy: Redundancy;
}
const redundancyCache: Record<string, IconifyAPIInternalStorage> =
Object.create(null);
/**
* Get Redundancy instance for provider
*/
function getRedundancyCache(
provider: string
): IconifyAPIInternalStorage | undefined {
if (redundancyCache[provider] === void 0) {
const config = getAPIConfig(provider);
if (!config) {
// Configuration is not set!
return;
}
const redundancy = initRedundancy(config);
const cachedReundancy = {
config,
redundancy,
};
redundancyCache[provider] = cachedReundancy;
}
return redundancyCache[provider];
}
/**
* Send API query
*/
export function sendAPIQuery(
target: string | PartialIconifyAPIConfig,
query: IconifyAPIQueryParams,
callback: QueryDoneCallback
): QueryAbortCallback {
let redundancy: Redundancy | undefined;
let send: IconifyAPISendQuery | undefined;
if (typeof target === 'string') {
// Get API module
const api = getAPIModule(target);
if (!api) {
// No API module
// Return "424 Failed Dependency" (its not meant to be used like that, but it is the closest match)
callback(void 0, 424);
return emptyCallback;
}
send = api.send;
// Get Redundancy instance
const cached = getRedundancyCache(target);
if (cached) {
redundancy = cached.redundancy;
}
} else {
const config = createAPIConfig(target);
if (config) {
redundancy = initRedundancy(config);
// Use default API provider
const api = getAPIModule('');
if (api) {
send = api.send;
}
}
}
if (!redundancy || !send) {
// No way to load icons because configuration is not set!
callback(void 0, 424);
return emptyCallback;
}
// Send API query, return function to abort query
return redundancy.query(query, send as QueryModuleCallback, callback)()
.abort;
}

View File

@ -1,5 +1,5 @@
import type { IconifyJSON } from '@iconify/types';
import type { CacheIcons, LoadIconsCache } from '../interfaces/cache';
import type { CacheIcons, LoadIconsCache } from '../cache';
import { getStorage, addIconSet } from '../storage/storage';
interface StorageType<T> {
@ -68,7 +68,7 @@ export const emptyList: StorageEmptyList = {
type FakeWindow = Record<string, typeof localStorage>;
let _window: FakeWindow =
typeof window === 'undefined' ? {} : ((window as unknown) as FakeWindow);
typeof window === 'undefined' ? {} : (window as unknown as FakeWindow);
export function mock(fakeWindow: FakeWindow): void {
loaded = false;
_window = fakeWindow;

View File

@ -9,3 +9,13 @@ export type CacheIcons = (provider: string, data: IconifyJSON) => void;
* Function to load icons from cache
*/
export type LoadIconsCache = () => void;
/**
* Module
*/
interface CacheModule {
store?: CacheIcons;
load?: LoadIconsCache;
}
export const cache: CacheModule = {};

View File

@ -1,15 +0,0 @@
import type { IconifyLoadIcons } from './loader';
import type { IconifyIconName } from '@iconify/utils/lib/icon/name';
/**
* Function to check if icon is pending
*/
export type IsPending = (icon: IconifyIconName) => boolean;
/**
* API interface
*/
export interface IconifyAPI {
isPending: IsPending;
loadIcons: IconifyLoadIcons;
}

View File

@ -1,26 +0,0 @@
import type { IconifyIconName } from '@iconify/utils/lib/icon/name';
/**
* Function to abort loading (usually just removes callback because loading is already in progress)
*/
export type IconifyIconLoaderAbort = () => void;
/**
* Loader callback
*
* Provides list of icons that have been loaded
*/
export type IconifyIconLoaderCallback = (
loaded: IconifyIconName[],
missing: IconifyIconName[],
pending: IconifyIconName[],
unsubscribe: IconifyIconLoaderAbort
) => void;
/**
* Function to load icons
*/
export type IconifyLoadIcons = (
icons: (IconifyIconName | string)[],
callback?: IconifyIconLoaderCallback
) => IconifyIconLoaderAbort;

View File

@ -1,18 +0,0 @@
import type { CacheIcons } from './interfaces/cache';
import type { IconifyAPI } from './interfaces/api';
/**
* Dynamic modules.
*
* Used as storage for optional functions that may or may not exist.
* Each module must be set after including correct function for it, see build files as examples.
*/
interface Modules {
// API module
api?: IconifyAPI;
// Cache module (only function that stores cache. loading cache should be done when assigning module)
cache?: CacheIcons;
}
export const coreModules: Modules = {};

View File

@ -6,8 +6,8 @@ import type { PendingQueryItem } from '@cyberalien/redundancy';
import type { IconifyAPIConfig } from '../../lib/api/config';
import { setAPIConfig, getAPIConfig } from '../../lib/api/config';
import type {
APIIconsQueryParams,
APIQueryParams,
IconifyAPIIconsQueryParams,
IconifyAPIQueryParams,
IconifyAPIModule,
} from '../../lib/api/modules';
import { setAPIModule, getAPIModule } from '../../lib/api/modules';
@ -25,8 +25,8 @@ describe('Testing API modules', () => {
provider: string,
prefix: string,
icons: string[]
): APIIconsQueryParams[] => {
const item: APIIconsQueryParams = {
): IconifyAPIIconsQueryParams[] => {
const item: IconifyAPIIconsQueryParams = {
type: 'icons',
provider,
prefix,
@ -37,7 +37,7 @@ describe('Testing API modules', () => {
const sendQuery = (
host: string,
params: APIQueryParams,
params: IconifyAPIQueryParams,
item: PendingQueryItem
): void => {
throw new Error('Unexpected API call');

View File

@ -5,11 +5,11 @@ import { expect } from 'chai';
import type { PendingQueryItem } from '@cyberalien/redundancy';
import { setAPIConfig } from '../../lib/api/config';
import type {
APIIconsQueryParams,
APIQueryParams,
IconifyAPIIconsQueryParams,
IconifyAPIQueryParams,
} from '../../lib/api/modules';
import { setAPIModule } from '../../lib/api/modules';
import { API } from '../../lib/api/';
import { loadIcons, isPending } from '../../lib/api/icons';
describe('Testing API loadIcons', () => {
let prefixCounter = 0;
@ -35,8 +35,8 @@ describe('Testing API loadIcons', () => {
provider: string,
prefix: string,
icons: string[]
): APIIconsQueryParams[] => {
const item: APIIconsQueryParams = {
): IconifyAPIIconsQueryParams[] => {
const item: IconifyAPIIconsQueryParams = {
type: 'icons',
provider,
prefix,
@ -48,7 +48,7 @@ describe('Testing API loadIcons', () => {
asyncCounter++;
// Test input and return as one item
const expected: APIIconsQueryParams = {
const expected: IconifyAPIIconsQueryParams = {
type: 'icons',
provider,
prefix,
@ -61,7 +61,7 @@ describe('Testing API loadIcons', () => {
const sendQuery = (
host: string,
params: APIQueryParams,
params: IconifyAPIQueryParams,
item: PendingQueryItem
): void => {
// This callback should be called after prepareQuery
@ -72,7 +72,7 @@ describe('Testing API loadIcons', () => {
// Test input
expect(host).to.be.equal('https://api1.local');
const expected: APIQueryParams = {
const expected: IconifyAPIQueryParams = {
type: 'icons',
provider,
prefix,
@ -103,7 +103,7 @@ describe('Testing API loadIcons', () => {
});
// Load icons
API.loadIcons(
loadIcons(
[
// as icon
{
@ -135,14 +135,14 @@ describe('Testing API loadIcons', () => {
expect(pending).to.be.eql([]);
expect(
API.isPending({
isPending({
provider,
prefix,
name: 'icon1',
})
).to.be.equal(false);
expect(
API.isPending({ provider, prefix, name: 'icon3' })
isPending({ provider, prefix, name: 'icon3' })
).to.be.equal(false);
done();
@ -150,10 +150,10 @@ describe('Testing API loadIcons', () => {
);
// Test isPending
expect(API.isPending({ provider, prefix, name: 'icon1' })).to.be.equal(
expect(isPending({ provider, prefix, name: 'icon1' })).to.be.equal(
true
);
expect(API.isPending({ provider, prefix, name: 'icon3' })).to.be.equal(
expect(isPending({ provider, prefix, name: 'icon3' })).to.be.equal(
false
);
@ -176,11 +176,11 @@ describe('Testing API loadIcons', () => {
provider: string,
prefix: string,
icons: string[]
): APIIconsQueryParams[] => {
): IconifyAPIIconsQueryParams[] => {
// Split all icons in multiple queries, one icon per query
const results: APIIconsQueryParams[] = [];
const results: IconifyAPIIconsQueryParams[] = [];
icons.forEach((icon) => {
const item: APIIconsQueryParams = {
const item: IconifyAPIIconsQueryParams = {
type: 'icons',
provider,
prefix,
@ -197,7 +197,7 @@ describe('Testing API loadIcons', () => {
let queryCounter = 0;
const sendQuery = (
host: string,
params: APIQueryParams,
params: IconifyAPIQueryParams,
item: PendingQueryItem
): void => {
// Test input
@ -210,7 +210,7 @@ describe('Testing API loadIcons', () => {
// Icon names should match queryCounter: 'icon1' on first run, 'icon2' on second run
queryCounter++;
const expected: APIQueryParams = {
const expected: IconifyAPIQueryParams = {
type: 'icons',
provider,
prefix,
@ -240,7 +240,7 @@ describe('Testing API loadIcons', () => {
// Load icons
let callbackCalled = false;
API.loadIcons(
loadIcons(
[
provider + ':' + prefix + ':icon1',
provider + ':' + prefix + ':icon2',
@ -285,8 +285,8 @@ describe('Testing API loadIcons', () => {
provider: string,
prefix: string,
icons: string[]
): APIIconsQueryParams[] => {
const item: APIIconsQueryParams = {
): IconifyAPIIconsQueryParams[] => {
const item: IconifyAPIIconsQueryParams = {
type: 'icons',
provider,
prefix,
@ -298,7 +298,7 @@ describe('Testing API loadIcons', () => {
let queryCounter = 0;
const sendQuery = (
host: string,
params: APIQueryParams,
params: IconifyAPIQueryParams,
item: PendingQueryItem
): void => {
queryCounter++;
@ -342,7 +342,7 @@ describe('Testing API loadIcons', () => {
// Load icons
let callbackCalled = false;
API.loadIcons(
loadIcons(
[
provider + ':' + prefix + ':icon1',
provider + ':' + prefix + ':icon2',
@ -388,8 +388,8 @@ describe('Testing API loadIcons', () => {
provider: string,
prefix: string,
icons: string[]
): APIIconsQueryParams[] => {
const item: APIIconsQueryParams = {
): IconifyAPIIconsQueryParams[] => {
const item: IconifyAPIIconsQueryParams = {
type: 'icons',
provider,
prefix,
@ -401,7 +401,7 @@ describe('Testing API loadIcons', () => {
let queryCounter = 0;
const sendQuery = (
host: string,
params: APIQueryParams,
params: IconifyAPIQueryParams,
item: PendingQueryItem
): void => {
queryCounter++;
@ -472,7 +472,7 @@ describe('Testing API loadIcons', () => {
// Load icons
let callbackCalled = false;
API.loadIcons(
loadIcons(
[
provider + ':' + prefix + ':icon1',
provider + ':' + prefix + ':icon2',
@ -501,7 +501,7 @@ describe('Testing API loadIcons', () => {
// Send another query on next tick
setTimeout(() => {
let callbackCalled = false;
API.loadIcons(
loadIcons(
[
provider + ':' + prefix + ':icon3',
provider + ':' + prefix + ':icon4',
@ -551,8 +551,8 @@ describe('Testing API loadIcons', () => {
provider: string,
prefix: string,
icons: string[]
): APIIconsQueryParams[] => {
const item: APIIconsQueryParams = {
): IconifyAPIIconsQueryParams[] => {
const item: IconifyAPIIconsQueryParams = {
type: 'icons',
provider,
prefix,
@ -564,7 +564,7 @@ describe('Testing API loadIcons', () => {
let queryCounter = 0;
const sendQuery = (
host: string,
params: APIQueryParams,
params: IconifyAPIQueryParams,
item: PendingQueryItem
): void => {
queryCounter++;
@ -638,7 +638,7 @@ describe('Testing API loadIcons', () => {
// Load icons
let callbackCalled = false;
API.loadIcons(
loadIcons(
[
provider + ':' + prefix + ':icon1',
provider + ':' + prefix + ':icon2',
@ -667,7 +667,7 @@ describe('Testing API loadIcons', () => {
// Send another query on next tick for different prefix that shares configuration
setTimeout(() => {
let callbackCalled = false;
API.loadIcons(
loadIcons(
[
provider + ':' + prefix2 + ':icon2',
provider + ':' + prefix2 + ':icon4',

View File

@ -4,7 +4,7 @@ import 'mocha';
import { expect } from 'chai';
import { setAPIConfig } from '../../lib/api/config';
import { setAPIModule } from '../../lib/api/modules';
import { API } from '../../lib/api/';
import { loadIcons } from '../../lib/api/icons';
import type { IconifyMockAPIDelayDoneCallback } from '../../lib/api/modules/mock';
import { mockAPIModule, mockAPIData } from '../../lib/api/modules/mock';
import { getStorage, iconExists } from '../../lib/storage/storage';
@ -37,7 +37,7 @@ describe('Testing mock API module', () => {
let isSync = true;
API.loadIcons(
loadIcons(
[
{
provider,
@ -101,7 +101,7 @@ describe('Testing mock API module', () => {
let isSync = true;
API.loadIcons(
loadIcons(
[
{
provider,
@ -180,7 +180,7 @@ describe('Testing mock API module', () => {
let callbackCounter = 0;
API.loadIcons(
loadIcons(
[
{
provider,
@ -278,7 +278,7 @@ describe('Testing mock API module', () => {
});
// Load icons
API.loadIcons([
loadIcons([
{
provider,
prefix,

View File

@ -2,18 +2,14 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import 'mocha';
import { expect } from 'chai';
import { setAPIConfig } from '../../lib/api/config';
import { setAPIModule } from '../../lib/api/modules';
import { API } from '../../lib/api/';
import { loadIcons } from '../../lib/api/icons';
import { mockAPIModule, mockAPIData } from '../../lib/api/modules/mock';
import { allowSimpleNames } from '../../lib/storage/functions';
describe('Testing simple names with API module', () => {
// Set API config and allow simple names
before(() => {
setAPIConfig('', {
resources: ['https://api1.local'],
});
allowSimpleNames(true);
setAPIModule('', mockAPIModule);
});
@ -56,7 +52,7 @@ describe('Testing simple names with API module', () => {
},
});
API.loadIcons(
loadIcons(
[
{
provider: '',

View File

@ -0,0 +1,86 @@
/* eslint-disable @typescript-eslint/no-unused-vars-experimental */
/* eslint-disable @typescript-eslint/no-unused-vars */
import 'mocha';
import { expect } from 'chai';
import crossFetch from 'cross-fetch';
import { sendAPIQuery } from '../../lib/api/query';
import { setAPIModule } from '../../lib/api/modules';
import { fetchAPIModule, setFetch } from '../../lib/api/modules/fetch';
import { setAPIConfig } from '../../lib/api/config';
import { mockAPIModule } from '../../lib/api/modules/mock';
describe('Testing live API with fetch', () => {
let counter = 0;
function nextProvider(): string {
return 'fetch-' + counter++;
}
const host = 'https://api.iconify.design';
// Set fetch module
before(() => {
setFetch(crossFetch);
setAPIModule('', fetchAPIModule);
});
after(() => {
setAPIModule('', mockAPIModule);
});
it('Missing API configuration', (done) => {
const provider = nextProvider();
sendAPIQuery(
provider,
{
type: 'custom',
provider,
uri: '/collections',
},
(data, error) => {
expect(error).to.be.equal(424);
expect(data).to.be.equal(void 0);
done();
}
);
});
it('Custom request with provider', (done) => {
const provider = nextProvider();
expect(
setAPIConfig(provider, {
resources: [host],
})
).to.be.equal(true);
sendAPIQuery(
provider,
{
type: 'custom',
provider,
uri: '/collections',
},
(data, error) => {
expect(error).to.be.equal(void 0);
expect(typeof data).to.be.equal('object');
done();
}
);
});
it('Custom request with host', (done) => {
sendAPIQuery(
{
resources: [host],
},
{
type: 'custom',
uri: '/collections',
},
(data, error) => {
expect(error).to.be.equal(void 0);
expect(typeof data).to.be.equal('object');
done();
}
);
});
});

View File

@ -7,8 +7,7 @@ import { getIconData } from '@iconify/core/lib/storage/functions';
import { fullIcon, FullIconifyIcon } from '@iconify/utils/lib/icon';
// API
import { API } from '@iconify/core/lib/api/';
import type { IconifyIconLoaderAbort } from '@iconify/core/lib/interfaces/loader';
import { loadIcons, IconifyIconLoaderAbort } from '@iconify/core/lib/api/icons';
// Component stuff
import type { IconifyIconProps } from './props';
@ -127,7 +126,7 @@ export class IconifyIconComponent extends Component<IconifyIconProps> {
this._icon = {
name: icon,
className,
abort: API.loadIcons([iconName], () => {
abort: loadIcons([iconName], () => {
if (!this.isDestroyed && this._icon?.name === icon) {
// Loaded
const data = getIconData(iconName);

View File

@ -18,11 +18,7 @@ import {
} from '@iconify/core/lib/builder/functions';
import type { IconifyIconBuildResult } from '@iconify/utils/lib/svg/build';
// Modules
import { coreModules } from '@iconify/core/lib/modules';
// API
import { API } from '@iconify/core/lib/api/';
import {
IconifyAPIFunctions,
IconifyAPIInternalFunctions,
@ -37,26 +33,26 @@ import {
IconifyAPIModule,
IconifyAPISendQuery,
IconifyAPIPrepareIconsQuery,
GetIconifyAPIModule,
} from '@iconify/core/lib/api/modules';
import { getAPIModule as getJSONPAPIModule } from '@iconify/core/lib/api/modules/jsonp';
import { jsonpAPIModule } from '@iconify/core/lib/api/modules/jsonp';
import {
getAPIModule as getFetchAPIModule,
fetchAPIModule,
getFetch,
setFetch,
} from '@iconify/core/lib/api/modules/fetch';
import {
setAPIConfig,
PartialIconifyAPIConfig,
IconifyAPIConfig,
getAPIConfig,
GetAPIConfig,
} from '@iconify/core/lib/api/config';
import type {
IconifyIconLoaderCallback,
IconifyIconLoaderAbort,
} from '@iconify/core/lib/interfaces/loader';
} from '@iconify/core/lib/api/icons';
// Cache
import { cache } from '@iconify/core/lib/cache';
import { storeCache, loadCache } from '@iconify/core/lib/browser-storage';
import { toggleBrowserCache } from '@iconify/core/lib/browser-storage/functions';
import type {
@ -194,33 +190,15 @@ export const _api = APIInternalFunctions;
// Enable short names
allowSimpleNames(true);
// Set API
coreModules.api = API;
// Use Fetch API by default
let getAPIModule: GetIconifyAPIModule = getFetchAPIModule;
try {
if (typeof document !== 'undefined' && typeof window !== 'undefined') {
// If window and document exist, attempt to load whatever module is available, otherwise use Fetch API
getAPIModule =
typeof fetch === 'function' && typeof Promise === 'function'
? getFetchAPIModule
: getJSONPAPIModule;
}
} catch (err) {
//
}
setAPIModule('', getAPIModule(getAPIConfig));
// Set API module
setAPIModule('', getFetch() ? fetchAPIModule : jsonpAPIModule);
/**
* Function to enable node-fetch for getting icons on server side
*/
_api.setFetch = (nodeFetch: typeof fetch) => {
setFetch(nodeFetch);
if (getAPIModule !== getFetchAPIModule) {
getAPIModule = getFetchAPIModule;
setAPIModule('', getAPIModule(getAPIConfig));
}
setAPIModule('', fetchAPIModule);
};
/**
@ -228,7 +206,7 @@ _api.setFetch = (nodeFetch: typeof fetch) => {
*/
if (typeof document !== 'undefined' && typeof window !== 'undefined') {
// Set cache and load existing cache
coreModules.cache = storeCache;
cache.store = storeCache;
loadCache();
interface WindowWithIconifyStuff {

View File

@ -21,13 +21,13 @@ Iconify SVG framework is designed to be as easy to use as possible.
Add this line to your page to load Iconify SVG framework (you can add it to `<head>` section of the page or before `</body>`):
```html
<script src="https://code.iconify.design/2/2.0.4/iconify.min.js"></script>
<script src="https://code.iconify.design/2/2.1.0/iconify.min.js"></script>
```
or
```html
<script src="https://cdn.jsdelivr.net/npm/@iconify/iconify@2.0.4/dist/iconify.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@iconify/iconify@2.1.0/dist/iconify.min.js"></script>
```
or, if you are building a project with something like WebPack or Rollup, you can include the script by installing `@iconify/iconify` as a dependency and importing it in your project:

View File

@ -1,8 +1,8 @@
{
"name": "@iconify/iconify",
"description": "Unified SVG framework with over 70,000 icons to choose from",
"description": "Unified SVG framework with over 100,000 icons to choose from",
"author": "Vjacheslav Trushkin <cyberalien@gmail.com> (https://iconify.design)",
"version": "2.0.4",
"version": "2.1.0",
"license": "(Apache-2.0 OR GPL-2.0)",
"main": "./dist/iconify.min.js",
"types": "./dist/iconify.d.ts",

View File

@ -17,11 +17,9 @@ import {
builderFunctions,
} from '@iconify/core/lib/builder/functions';
// Modules
import { coreModules } from '@iconify/core/lib/modules';
// Cache
import { storeCache, loadCache } from '@iconify/core/lib/browser-storage/';
import { cache } from '@iconify/core/lib/cache';
import {
IconifyBrowserCacheFunctions,
IconifyBrowserCacheType,
@ -38,30 +36,28 @@ import {
IconifyAPICustomQueryParams,
IconifyAPIMergeQueryParams,
} from '@iconify/core/lib/api/functions';
import { API } from '@iconify/core/lib/api/';
import {
setAPIModule,
IconifyAPIModule,
IconifyAPISendQuery,
IconifyAPIPrepareIconsQuery,
GetIconifyAPIModule,
} from '@iconify/core/lib/api/modules';
import {
setAPIConfig,
PartialIconifyAPIConfig,
IconifyAPIConfig,
getAPIConfig,
GetAPIConfig,
} from '@iconify/core/lib/api/config';
import { getAPIModule as getJSONPAPIModule } from '@iconify/core/lib/api/modules/jsonp';
import { jsonpAPIModule } from '@iconify/core/lib/api/modules/jsonp';
import {
getAPIModule as getFetchAPIModule,
fetchAPIModule,
getFetch,
setFetch,
} from '@iconify/core/lib/api/modules/fetch';
import {
IconifyIconLoaderCallback,
IconifyIconLoaderAbort,
} from '@iconify/core/lib/interfaces/loader';
} from '@iconify/core/lib/api/icons';
// Other
import { IconifyCommonFunctions, commonFunctions } from './common';
@ -157,33 +153,15 @@ const Iconify = {
/**
* Initialise stuff
*/
// Set API
coreModules.api = API;
// Check for Fetch API
let getAPIModule: GetIconifyAPIModule = getFetchAPIModule;
try {
if (typeof document !== 'undefined' && typeof window !== 'undefined') {
// If window and document exist, attempt to load whatever module is available, otherwise use Fetch API
getAPIModule =
typeof fetch === 'function' && typeof Promise === 'function'
? getFetchAPIModule
: getJSONPAPIModule;
}
} catch (err) {
//
}
setAPIModule('', getAPIModule(getAPIConfig));
// Set API module
setAPIModule('', getFetch() ? fetchAPIModule : jsonpAPIModule);
/**
* Function to enable node-fetch for getting icons on server side
*/
Iconify._api.setFetch = (nodeFetch: typeof fetch) => {
setFetch(nodeFetch);
if (getAPIModule !== getFetchAPIModule) {
getAPIModule = getFetchAPIModule;
setAPIModule('', getAPIModule(getAPIConfig));
}
setAPIModule('', fetchAPIModule);
};
/**
@ -191,7 +169,7 @@ Iconify._api.setFetch = (nodeFetch: typeof fetch) => {
*/
if (typeof document !== 'undefined' && typeof window !== 'undefined') {
// Set cache and load existing cache
coreModules.cache = storeCache;
cache.store = storeCache;
loadCache();
interface WindowWithIconifyStuff {

View File

@ -6,7 +6,7 @@ interface OldIEElement extends HTMLElement {
/**
* Execute function when DOM is ready
*/
export function onReady(callback): void {
export function onReady(callback: () => void): void {
const doc = document;
if (
doc.readyState === 'complete' ||

View File

@ -1,6 +1,6 @@
import { IconifyIconName } from '@iconify/utils/lib/icon/name';
import { getStorage, getIcon } from '@iconify/core/lib/storage/storage';
import { coreModules } from '@iconify/core/lib/modules';
import { isPending, loadIcons } from '@iconify/core/lib/api/icons';
import { FullIconifyIcon } from '@iconify/utils/lib/icon';
import { findPlaceholders } from './finder';
import { IconifyElementData, elementDataProperty } from './element';
@ -12,7 +12,7 @@ import {
removeObservedNode,
observeNode,
} from './observer';
import { findRootNode, addRootNode, listRootNodes } from './root';
import { findRootNode, listRootNodes } from './root';
/**
* Flag to avoid scanning DOM too often
@ -77,8 +77,10 @@ export function scanDOM(node?: ObservedNode, addTempNode = false): void {
scanQueued = false;
// List of icons to load: [provider][prefix][name] = boolean
const loadIcons: Record<string, Record<string, Record<string, boolean>>> =
Object.create(null);
const iconsToLoad: Record<
string,
Record<string, Record<string, boolean>>
> = Object.create(null);
// Get placeholders
(node ? [node] : listRootNodes()).forEach((node) => {
@ -112,8 +114,7 @@ export function scanDOM(node?: ObservedNode, addTempNode = false): void {
case 'loading':
if (
coreModules.api &&
coreModules.api.isPending({
isPending({
provider,
prefix,
name,
@ -162,18 +163,16 @@ export function scanDOM(node?: ObservedNode, addTempNode = false): void {
return;
}
if (coreModules.api) {
if (!coreModules.api.isPending({ provider, prefix, name })) {
// Add icon to loading queue
if (loadIcons[provider] === void 0) {
loadIcons[provider] = Object.create(null);
}
const providerLoadIcons = loadIcons[provider];
if (providerLoadIcons[prefix] === void 0) {
providerLoadIcons[prefix] = Object.create(null);
}
providerLoadIcons[prefix][name] = true;
if (!isPending({ provider, prefix, name })) {
// Add icon to loading queue
if (iconsToLoad[provider] === void 0) {
iconsToLoad[provider] = Object.create(null);
}
const providerIconsToLoad = iconsToLoad[provider];
if (providerIconsToLoad[prefix] === void 0) {
providerIconsToLoad[prefix] = Object.create(null);
}
providerIconsToLoad[prefix][name] = true;
}
// Mark as loading
@ -200,23 +199,20 @@ export function scanDOM(node?: ObservedNode, addTempNode = false): void {
});
// Load icons
if (coreModules.api) {
const api = coreModules.api;
Object.keys(loadIcons).forEach((provider) => {
const providerLoadIcons = loadIcons[provider];
Object.keys(providerLoadIcons).forEach((prefix) => {
api.loadIcons(
Object.keys(providerLoadIcons[prefix]).map((name) => {
const icon: IconifyIconName = {
provider,
prefix,
name,
};
return icon;
}),
checkPendingIcons
);
});
Object.keys(iconsToLoad).forEach((provider) => {
const providerIconsToLoad = iconsToLoad[provider];
Object.keys(providerIconsToLoad).forEach((prefix) => {
loadIcons(
Object.keys(providerIconsToLoad[prefix]).map((name) => {
const icon: IconifyIconName = {
provider,
prefix,
name,
};
return icon;
}),
checkPendingIcons
);
});
}
});
}

View File

@ -15,14 +15,14 @@ Iconify._api.setAPIModule(provider, mockAPIModule);
// Set data
mockAPIData({
type: 'icons',
provider,
prefix,
response: {
prefix,
icons: {
home: {
body:
'<path d="M10 20v-6h4v6h5v-8h3L12 3L2 12h3v8h5z" fill="currentColor"/>',
body: '<path d="M10 20v-6h4v6h5v-8h3L12 3L2 12h3v8h5z" fill="currentColor"/>',
},
},
width: 24,

View File

@ -10,7 +10,7 @@ const prefix = 'demo';
// Set API module for provider
addAPIProvider(provider, {
resources: 'http://localhost',
resources: ['http://localhost'],
rotate: 10000,
timeout: 10000,
});
@ -18,6 +18,7 @@ _api.setAPIModule(provider, mockAPIModule);
// Set mock data
mockAPIData({
type: 'icons',
provider,
prefix,
response: {

View File

@ -21,11 +21,7 @@ import {
import type { IconifyIconBuildResult } from '@iconify/utils/lib/svg/build';
import { fullIcon } from '@iconify/utils/lib/icon';
// Modules
import { coreModules } from '@iconify/core/lib/modules';
// API
import { API } from '@iconify/core/lib/api/';
import {
IconifyAPIFunctions,
IconifyAPIInternalFunctions,
@ -40,26 +36,26 @@ import {
IconifyAPIModule,
IconifyAPISendQuery,
IconifyAPIPrepareIconsQuery,
GetIconifyAPIModule,
} from '@iconify/core/lib/api/modules';
import { getAPIModule as getJSONPAPIModule } from '@iconify/core/lib/api/modules/jsonp';
import { jsonpAPIModule } from '@iconify/core/lib/api/modules/jsonp';
import {
getAPIModule as getFetchAPIModule,
fetchAPIModule,
getFetch,
setFetch,
} from '@iconify/core/lib/api/modules/fetch';
import {
setAPIConfig,
PartialIconifyAPIConfig,
IconifyAPIConfig,
getAPIConfig,
GetAPIConfig,
} from '@iconify/core/lib/api/config';
import type {
IconifyIconLoaderCallback,
IconifyIconLoaderAbort,
} from '@iconify/core/lib/interfaces/loader';
} from '@iconify/core/lib/api/icons';
// Cache
import { cache } from '@iconify/core/lib/cache';
import { storeCache, loadCache } from '@iconify/core/lib/browser-storage';
import { toggleBrowserCache } from '@iconify/core/lib/browser-storage/functions';
import type {
@ -200,33 +196,15 @@ export const _api = APIInternalFunctions;
// Enable short names
allowSimpleNames(true);
// Set API
coreModules.api = API;
// Use Fetch API by default
let getAPIModule: GetIconifyAPIModule = getFetchAPIModule;
try {
if (typeof document !== 'undefined' && typeof window !== 'undefined') {
// If window and document exist, attempt to load whatever module is available, otherwise use Fetch API
getAPIModule =
typeof fetch === 'function' && typeof Promise === 'function'
? getFetchAPIModule
: getJSONPAPIModule;
}
} catch (err) {
//
}
setAPIModule('', getAPIModule(getAPIConfig));
// Set API module
setAPIModule('', getFetch() ? fetchAPIModule : jsonpAPIModule);
/**
* Function to enable node-fetch for getting icons on server side
*/
_api.setFetch = (nodeFetch: typeof fetch) => {
setFetch(nodeFetch);
if (getAPIModule !== getFetchAPIModule) {
getAPIModule = getFetchAPIModule;
setAPIModule('', getAPIModule(getAPIConfig));
}
setAPIModule('', fetchAPIModule);
};
/**
@ -234,7 +212,7 @@ _api.setFetch = (nodeFetch: typeof fetch) => {
*/
if (typeof document !== 'undefined' && typeof window !== 'undefined') {
// Set cache and load existing cache
coreModules.cache = storeCache;
cache.store = storeCache;
loadCache();
interface WindowWithIconifyStuff {
@ -402,7 +380,7 @@ class IconComponent extends React.Component<
this._setData(null);
this._loading = {
name: icon,
abort: API.loadIcons(
abort: loadIcons(
[iconName],
this._checkIcon.bind(this, false)
),

View File

@ -8,6 +8,7 @@ describe('Testing fake API', () => {
const name = 'mock-test';
const iconName = `@${provider}:${prefix}:${name}`;
mockAPIData({
type: 'icons',
provider,
prefix,
response: {

View File

@ -19,6 +19,7 @@ describe('Rendering icon', () => {
let onLoadCalled = false;
mockAPIData({
type: 'icons',
provider,
prefix,
response: {
@ -94,6 +95,7 @@ describe('Rendering icon', () => {
let onLoadCalled = false;
mockAPIData({
type: 'icons',
provider,
prefix,
response: {
@ -187,6 +189,7 @@ describe('Rendering icon', () => {
const name = 'missing-icon';
const iconName = `@${provider}:${prefix}:${name}`;
mockAPIData({
type: 'icons',
provider,
prefix,
response: 404,

View File

@ -46,6 +46,7 @@ describe('Rendering icon', () => {
};
mockAPIData({
type: 'icons',
provider,
prefix,
response: {
@ -110,6 +111,7 @@ describe('Rendering icon', () => {
});
mockAPIData({
type: 'icons',
provider,
prefix,
response: {
@ -197,6 +199,7 @@ describe('Rendering icon', () => {
let isSync = true;
mockAPIData({
type: 'icons',
provider,
prefix,
response: {
@ -215,6 +218,7 @@ describe('Rendering icon', () => {
});
mockAPIData({
type: 'icons',
provider,
prefix,
response: {
@ -300,6 +304,7 @@ describe('Rendering icon', () => {
const className = `iconify iconify--${prefix} iconify--${provider}`;
mockAPIData({
type: 'icons',
provider,
prefix,
response: {

View File

@ -17,6 +17,7 @@ describe('Testing references', () => {
const iconName = `@${provider}:${prefix}:${name}`;
mockAPIData({
type: 'icons',
provider,
prefix,
response: {
@ -81,6 +82,7 @@ describe('Testing references', () => {
let gotRef = false;
mockAPIData({
type: 'icons',
provider,
prefix,
response: {
@ -139,6 +141,7 @@ describe('Testing references', () => {
let gotRef = false;
mockAPIData({
type: 'icons',
provider,
prefix,
response: 404,

View File

@ -20,11 +20,7 @@ import {
import type { IconifyIconBuildResult } from '@iconify/utils/lib/svg/build';
import { fullIcon, IconifyIcon } from '@iconify/utils/lib/icon';
// Modules
import { coreModules } from '@iconify/core/lib/modules';
// API
import { API } from '@iconify/core/lib/api/';
import {
IconifyAPIFunctions,
IconifyAPIInternalFunctions,
@ -39,26 +35,26 @@ import {
IconifyAPIModule,
IconifyAPISendQuery,
IconifyAPIPrepareIconsQuery,
GetIconifyAPIModule,
} from '@iconify/core/lib/api/modules';
import { getAPIModule as getJSONPAPIModule } from '@iconify/core/lib/api/modules/jsonp';
import { jsonpAPIModule } from '@iconify/core/lib/api/modules/jsonp';
import {
getAPIModule as getFetchAPIModule,
fetchAPIModule,
getFetch,
setFetch,
} from '@iconify/core/lib/api/modules/fetch';
import {
setAPIConfig,
PartialIconifyAPIConfig,
IconifyAPIConfig,
getAPIConfig,
GetAPIConfig,
} from '@iconify/core/lib/api/config';
import type {
IconifyIconLoaderCallback,
IconifyIconLoaderAbort,
} from '@iconify/core/lib/interfaces/loader';
} from '@iconify/core/lib/api/icons';
// Cache
import { cache } from '@iconify/core/lib/cache';
import { storeCache, loadCache } from '@iconify/core/lib/browser-storage';
import { toggleBrowserCache } from '@iconify/core/lib/browser-storage/functions';
import type {
@ -197,33 +193,15 @@ export const _api = APIInternalFunctions;
// Enable short names
allowSimpleNames(true);
// Set API
coreModules.api = API;
// Use Fetch API by default
let getAPIModule: GetIconifyAPIModule = getFetchAPIModule;
try {
if (typeof document !== 'undefined' && typeof window !== 'undefined') {
// If window and document exist, attempt to load whatever module is available, otherwise use Fetch API
getAPIModule =
typeof fetch === 'function' && typeof Promise === 'function'
? getFetchAPIModule
: getJSONPAPIModule;
}
} catch (err) {
//
}
setAPIModule('', getAPIModule(getAPIConfig));
// Set API module
setAPIModule('', getFetch() ? fetchAPIModule : jsonpAPIModule);
/**
* Function to enable node-fetch for getting icons on server side
*/
_api.setFetch = (nodeFetch: typeof fetch) => {
setFetch(nodeFetch);
if (getAPIModule !== getFetchAPIModule) {
getAPIModule = getFetchAPIModule;
setAPIModule('', getAPIModule(getAPIConfig));
}
setAPIModule('', fetchAPIModule);
};
/**
@ -231,7 +209,7 @@ _api.setFetch = (nodeFetch: typeof fetch) => {
*/
if (typeof document !== 'undefined' && typeof window !== 'undefined') {
// Set cache and load existing cache
coreModules.cache = storeCache;
cache.store = storeCache;
loadCache();
interface WindowWithIconifyStuff {
@ -380,7 +358,7 @@ export function checkIconState(
state.name = '';
state.loading = {
name: icon,
abort: API.loadIcons([iconName], callback),
abort: loadIcons([iconName], callback),
};
}
return null;

View File

@ -8,6 +8,7 @@ describe('Testing fake API', () => {
const name = 'mock-test';
const iconName = `@${provider}:${prefix}:${name}`;
mockAPIData({
type: 'icons',
provider,
prefix,
response: {

View File

@ -18,6 +18,7 @@ describe('Rendering icon', () => {
let onLoadCalled = false;
mockAPIData({
type: 'icons',
provider,
prefix,
response: {
@ -79,6 +80,7 @@ describe('Rendering icon', () => {
let onLoadCalled = false;
mockAPIData({
type: 'icons',
provider,
prefix,
response: {
@ -152,6 +154,7 @@ describe('Rendering icon', () => {
const iconName = `@${provider}:${prefix}:${name}`;
mockAPIData({
type: 'icons',
provider,
prefix,
response: 404,

View File

@ -29,6 +29,7 @@ describe('Rendering icon', () => {
let triggerSwap;
mockAPIData({
type: 'icons',
provider,
prefix,
response: {
@ -78,6 +79,7 @@ describe('Rendering icon', () => {
});
mockAPIData({
type: 'icons',
provider,
prefix,
response: {
@ -172,6 +174,7 @@ describe('Rendering icon', () => {
let triggerSwap;
mockAPIData({
type: 'icons',
provider,
prefix,
response: {
@ -193,6 +196,7 @@ describe('Rendering icon', () => {
});
mockAPIData({
type: 'icons',
provider,
prefix,
response: {
@ -280,6 +284,7 @@ describe('Rendering icon', () => {
let triggerSwap;
mockAPIData({
type: 'icons',
provider,
prefix,
response: {

View File

@ -30,11 +30,7 @@ import {
import { IconifyIconBuildResult } from '@iconify/utils/lib/svg/build';
import { fullIcon, IconifyIcon } from '@iconify/utils/lib/icon';
// Modules
import { coreModules } from '@iconify/core/lib/modules';
// API
import { API } from '@iconify/core/lib/api/';
import {
IconifyAPIFunctions,
IconifyAPIInternalFunctions,
@ -49,26 +45,26 @@ import {
IconifyAPIModule,
IconifyAPISendQuery,
IconifyAPIPrepareIconsQuery,
GetIconifyAPIModule,
} from '@iconify/core/lib/api/modules';
import { getAPIModule as getJSONPAPIModule } from '@iconify/core/lib/api/modules/jsonp';
import { jsonpAPIModule } from '@iconify/core/lib/api/modules/jsonp';
import {
getAPIModule as getFetchAPIModule,
fetchAPIModule,
getFetch,
setFetch,
} from '@iconify/core/lib/api/modules/fetch';
import {
setAPIConfig,
PartialIconifyAPIConfig,
IconifyAPIConfig,
getAPIConfig,
GetAPIConfig,
} from '@iconify/core/lib/api/config';
import {
IconifyIconLoaderCallback,
IconifyIconLoaderAbort,
} from '@iconify/core/lib/interfaces/loader';
} from '@iconify/core/lib/api/icons';
// Cache
import { cache } from '@iconify/core/lib/cache';
import { storeCache, loadCache } from '@iconify/core/lib/browser-storage';
import { toggleBrowserCache } from '@iconify/core/lib/browser-storage/functions';
import {
@ -208,33 +204,15 @@ export const _api = APIInternalFunctions;
// Enable short names
allowSimpleNames(true);
// Set API
coreModules.api = API;
// Use Fetch API by default
let getAPIModule: GetIconifyAPIModule = getFetchAPIModule;
try {
if (typeof document !== 'undefined' && typeof window !== 'undefined') {
// If window and document exist, attempt to load whatever module is available, otherwise use Fetch API
getAPIModule =
typeof fetch === 'function' && typeof Promise === 'function'
? getFetchAPIModule
: getJSONPAPIModule;
}
} catch (err) {
//
}
setAPIModule('', getAPIModule(getAPIConfig));
// Set API module
setAPIModule('', getFetch() ? fetchAPIModule : jsonpAPIModule);
/**
* Function to enable node-fetch for getting icons on server side
*/
_api.setFetch = (nodeFetch: typeof fetch) => {
setFetch(nodeFetch);
if (getAPIModule !== getFetchAPIModule) {
getAPIModule = getFetchAPIModule;
setAPIModule('', getAPIModule(getAPIConfig));
}
setAPIModule('', fetchAPIModule);
};
/**
@ -242,7 +220,7 @@ _api.setFetch = (nodeFetch: typeof fetch) => {
*/
if (typeof document !== 'undefined' && typeof window !== 'undefined') {
// Set cache and load existing cache
coreModules.cache = storeCache;
cache.store = storeCache;
loadCache();
interface WindowWithIconifyStuff {
@ -388,7 +366,7 @@ export const Icon = defineComponent({
this._name = '';
this._loadingIcon = {
name: icon,
abort: API.loadIcons([iconName], () => {
abort: loadIcons([iconName], () => {
this.counter++;
}),
};

View File

@ -8,6 +8,7 @@ describe('Testing fake API', () => {
const name = 'mock-test';
const iconName = `@${provider}:${prefix}:${name}`;
mockAPIData({
type: 'icons',
provider,
prefix,
response: {

View File

@ -19,6 +19,7 @@ describe('Rendering icon', () => {
let onLoadCalled = false;
mockAPIData({
type: 'icons',
provider,
prefix,
response: {
@ -84,6 +85,7 @@ describe('Rendering icon', () => {
let onLoadCalled = false;
mockAPIData({
type: 'icons',
provider,
prefix,
response: {
@ -163,6 +165,7 @@ describe('Rendering icon', () => {
const name = 'missing-icon';
const iconName = `@${provider}:${prefix}:${name}`;
mockAPIData({
type: 'icons',
provider,
prefix,
response: 404,

View File

@ -47,6 +47,7 @@ describe('Rendering icon', () => {
};
mockAPIData({
type: 'icons',
provider,
prefix,
response: {
@ -90,6 +91,7 @@ describe('Rendering icon', () => {
});
mockAPIData({
type: 'icons',
provider,
prefix,
response: {
@ -160,6 +162,7 @@ describe('Rendering icon', () => {
let isSync = true;
mockAPIData({
type: 'icons',
provider,
prefix,
response: {
@ -178,6 +181,7 @@ describe('Rendering icon', () => {
});
mockAPIData({
type: 'icons',
provider,
prefix,
response: {
@ -245,6 +249,7 @@ describe('Rendering icon', () => {
const className = `iconify iconify--${prefix} iconify--${provider}`;
mockAPIData({
type: 'icons',
provider,
prefix,
response: {

View File

@ -22,11 +22,7 @@ import {
import { IconifyIconBuildResult } from '@iconify/utils/lib/svg/build';
import { fullIcon, IconifyIcon } from '@iconify/utils/lib/icon';
// Modules
import { coreModules } from '@iconify/core/lib/modules';
// API
import { API } from '@iconify/core/lib/api/';
import {
IconifyAPIFunctions,
IconifyAPIInternalFunctions,
@ -41,26 +37,26 @@ import {
IconifyAPIModule,
IconifyAPISendQuery,
IconifyAPIPrepareIconsQuery,
GetIconifyAPIModule,
} from '@iconify/core/lib/api/modules';
import { getAPIModule as getJSONPAPIModule } from '@iconify/core/lib/api/modules/jsonp';
import { jsonpAPIModule } from '@iconify/core/lib/api/modules/jsonp';
import {
getAPIModule as getFetchAPIModule,
fetchAPIModule,
getFetch,
setFetch,
} from '@iconify/core/lib/api/modules/fetch';
import {
setAPIConfig,
PartialIconifyAPIConfig,
IconifyAPIConfig,
getAPIConfig,
GetAPIConfig,
} from '@iconify/core/lib/api/config';
import {
IconifyIconLoaderCallback,
IconifyIconLoaderAbort,
} from '@iconify/core/lib/interfaces/loader';
} from '@iconify/core/lib/api/icons';
// Cache
import { cache } from '@iconify/core/lib/cache';
import { storeCache, loadCache } from '@iconify/core/lib/browser-storage';
import { toggleBrowserCache } from '@iconify/core/lib/browser-storage/functions';
import {
@ -200,33 +196,15 @@ export const _api = APIInternalFunctions;
// Enable short names
allowSimpleNames(true);
// Set API
coreModules.api = API;
// Use Fetch API by default
let getAPIModule: GetIconifyAPIModule = getFetchAPIModule;
try {
if (typeof document !== 'undefined' && typeof window !== 'undefined') {
// If window and document exist, attempt to load whatever module is available, otherwise use Fetch API
getAPIModule =
typeof fetch === 'function' && typeof Promise === 'function'
? getFetchAPIModule
: getJSONPAPIModule;
}
} catch (err) {
//
}
setAPIModule('', getAPIModule(getAPIConfig));
// Set API module
setAPIModule('', getFetch() ? fetchAPIModule : jsonpAPIModule);
/**
* Function to enable node-fetch for getting icons on server side
*/
_api.setFetch = (nodeFetch: typeof fetch) => {
setFetch(nodeFetch);
if (getAPIModule !== getFetchAPIModule) {
getAPIModule = getFetchAPIModule;
setAPIModule('', getAPIModule(getAPIConfig));
}
setAPIModule('', fetchAPIModule);
};
/**
@ -234,7 +212,7 @@ _api.setFetch = (nodeFetch: typeof fetch) => {
*/
if (typeof document !== 'undefined' && typeof window !== 'undefined') {
// Set cache and load existing cache
coreModules.cache = storeCache;
cache.store = storeCache;
loadCache();
interface WindowWithIconifyStuff {
@ -378,7 +356,7 @@ export const Icon = Vue.extend({
this._name = '';
this._loadingIcon = {
name: icon,
abort: API.loadIcons([iconName], () => {
abort: loadIcons([iconName], () => {
this.$forceUpdate();
}),
};

View File

@ -3,11 +3,12 @@ import { mockAPIData } from '@iconify/core/lib/api/modules/mock';
import { provider, nextPrefix } from './load';
describe('Testing fake API', () => {
test('using fake API to load icon', done => {
test('using fake API to load icon', (done) => {
const prefix = nextPrefix();
const name = 'mock-test';
const iconName = `@${provider}:${prefix}:${name}`;
mockAPIData({
type: 'icons',
provider,
prefix,
response: {

View File

@ -18,6 +18,7 @@ describe('Rendering icon', () => {
let onLoadCalled = false;
mockAPIData({
type: 'icons',
provider,
prefix,
response: {
@ -83,6 +84,7 @@ describe('Rendering icon', () => {
let onLoadCalled = false;
mockAPIData({
type: 'icons',
provider,
prefix,
response: {
@ -163,6 +165,7 @@ describe('Rendering icon', () => {
const name = 'missing-icon';
const iconName = `@${provider}:${prefix}:${name}`;
mockAPIData({
type: 'icons',
provider,
prefix,
response: 404,

View File

@ -45,6 +45,7 @@ describe('Rendering icon', () => {
};
mockAPIData({
type: 'icons',
provider,
prefix,
response: {
@ -88,6 +89,7 @@ describe('Rendering icon', () => {
});
mockAPIData({
type: 'icons',
provider,
prefix,
response: {
@ -156,6 +158,7 @@ describe('Rendering icon', () => {
let isSync = true;
mockAPIData({
type: 'icons',
provider,
prefix,
response: {
@ -174,6 +177,7 @@ describe('Rendering icon', () => {
});
mockAPIData({
type: 'icons',
provider,
prefix,
response: {
@ -240,6 +244,7 @@ describe('Rendering icon', () => {
const className = `iconify iconify--${prefix} iconify--${provider}`;
mockAPIData({
type: 'icons',
provider,
prefix,
response: {