mirror of
https://github.com/iconify/iconify.git
synced 2025-01-22 14:48:24 +00:00
Implement icon providers (similar to namespaces)
This commit is contained in:
parent
0956dc7f9a
commit
2aad697264
@ -2,14 +2,14 @@ import mocha from 'mocha';
|
|||||||
import chai from 'chai';
|
import chai from 'chai';
|
||||||
import { FakeData, setFakeData, prepareQuery, sendQuery } from './fake-api';
|
import { FakeData, setFakeData, prepareQuery, sendQuery } from './fake-api';
|
||||||
import { API } from '@iconify/core/lib/api/';
|
import { API } from '@iconify/core/lib/api/';
|
||||||
import { setAPIModule } from '@iconify/core/lib/api/modules';
|
import { setDefaultAPIModule } from '@iconify/core/lib/api/modules';
|
||||||
import { setAPIConfig } from '@iconify/core/lib/api/config';
|
import { setAPIConfig } from '@iconify/core/lib/api/config';
|
||||||
import { coreModules } from '@iconify/core/lib/modules';
|
import { coreModules } from '@iconify/core/lib/modules';
|
||||||
|
|
||||||
const expect = chai.expect;
|
const expect = chai.expect;
|
||||||
|
|
||||||
// Set API
|
// Set API
|
||||||
setAPIModule({
|
setDefaultAPIModule({
|
||||||
prepare: prepareQuery,
|
prepare: prepareQuery,
|
||||||
send: sendQuery,
|
send: sendQuery,
|
||||||
});
|
});
|
||||||
@ -21,7 +21,8 @@ function nextPrefix(): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
describe('Testing fake API', () => {
|
describe('Testing fake API', () => {
|
||||||
it('Loading results', done => {
|
it('Loading results', (done) => {
|
||||||
|
const provider = nextPrefix();
|
||||||
const prefix = nextPrefix();
|
const prefix = nextPrefix();
|
||||||
const data: FakeData = {
|
const data: FakeData = {
|
||||||
icons: ['icon1', 'icon2'],
|
icons: ['icon1', 'icon2'],
|
||||||
@ -41,24 +42,26 @@ describe('Testing fake API', () => {
|
|||||||
height: 24,
|
height: 24,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
setAPIConfig(
|
setAPIConfig(provider, {
|
||||||
{
|
resources: ['https://api1.local', 'https://api2.local'],
|
||||||
resources: ['https://api1.local', 'https://api2.local'],
|
});
|
||||||
},
|
setFakeData(provider, prefix, data);
|
||||||
prefix
|
|
||||||
);
|
|
||||||
setFakeData(prefix, data);
|
|
||||||
|
|
||||||
// Attempt to load icons
|
// Attempt to load icons
|
||||||
API.loadIcons(
|
API.loadIcons(
|
||||||
[prefix + ':icon1', prefix + ':icon2'],
|
[
|
||||||
|
provider + ':' + prefix + ':icon1',
|
||||||
|
provider + ':' + prefix + ':icon2',
|
||||||
|
],
|
||||||
(loaded, missing, pending) => {
|
(loaded, missing, pending) => {
|
||||||
expect(loaded).to.be.eql([
|
expect(loaded).to.be.eql([
|
||||||
{
|
{
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
name: 'icon1',
|
name: 'icon1',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
name: 'icon2',
|
name: 'icon2',
|
||||||
},
|
},
|
||||||
@ -68,7 +71,8 @@ describe('Testing fake API', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Loading results with delay', done => {
|
it('Loading results with delay', (done) => {
|
||||||
|
const provider = nextPrefix();
|
||||||
const prefix = nextPrefix();
|
const prefix = nextPrefix();
|
||||||
const data: FakeData = {
|
const data: FakeData = {
|
||||||
icons: ['icon1', 'icon2'],
|
icons: ['icon1', 'icon2'],
|
||||||
@ -89,23 +93,22 @@ describe('Testing fake API', () => {
|
|||||||
height: 24,
|
height: 24,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
setAPIConfig(
|
setAPIConfig(provider, {
|
||||||
{
|
resources: ['https://api1.local', 'https://api2.local'],
|
||||||
resources: ['https://api1.local', 'https://api2.local'],
|
});
|
||||||
},
|
setFakeData(provider, prefix, data);
|
||||||
prefix
|
|
||||||
);
|
|
||||||
setFakeData(prefix, data);
|
|
||||||
|
|
||||||
// Attempt to load icons
|
// Attempt to load icons
|
||||||
const start = Date.now();
|
const start = Date.now();
|
||||||
API.loadIcons(
|
API.loadIcons(
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
name: 'icon1',
|
name: 'icon1',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
name: 'icon2',
|
name: 'icon2',
|
||||||
},
|
},
|
||||||
@ -113,10 +116,12 @@ describe('Testing fake API', () => {
|
|||||||
(loaded, missing, pending) => {
|
(loaded, missing, pending) => {
|
||||||
expect(loaded).to.be.eql([
|
expect(loaded).to.be.eql([
|
||||||
{
|
{
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
name: 'icon1',
|
name: 'icon1',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
name: 'icon2',
|
name: 'icon2',
|
||||||
},
|
},
|
||||||
@ -129,7 +134,8 @@ describe('Testing fake API', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Loading partial results', done => {
|
it('Loading partial results', (done) => {
|
||||||
|
const provider = nextPrefix();
|
||||||
const prefix = nextPrefix();
|
const prefix = nextPrefix();
|
||||||
const data: FakeData = {
|
const data: FakeData = {
|
||||||
icons: ['icon1'],
|
icons: ['icon1'],
|
||||||
@ -146,21 +152,21 @@ describe('Testing fake API', () => {
|
|||||||
height: 24,
|
height: 24,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
setAPIConfig(
|
setAPIConfig(provider, {
|
||||||
{
|
resources: ['https://api1.local', 'https://api2.local'],
|
||||||
resources: ['https://api1.local', 'https://api2.local'],
|
rotate: 20,
|
||||||
rotate: 20,
|
timeout: 100,
|
||||||
timeout: 100,
|
limit: 1,
|
||||||
limit: 1,
|
});
|
||||||
},
|
setFakeData(provider, prefix, data);
|
||||||
prefix
|
|
||||||
);
|
|
||||||
setFakeData(prefix, data);
|
|
||||||
|
|
||||||
// Attempt to load icons
|
// Attempt to load icons
|
||||||
let counter = 0;
|
let counter = 0;
|
||||||
API.loadIcons(
|
API.loadIcons(
|
||||||
[prefix + ':icon1', prefix + ':icon2'],
|
[
|
||||||
|
provider + ':' + prefix + ':icon1',
|
||||||
|
provider + ':' + prefix + ':icon2',
|
||||||
|
],
|
||||||
(loaded, missing, pending) => {
|
(loaded, missing, pending) => {
|
||||||
try {
|
try {
|
||||||
counter++;
|
counter++;
|
||||||
@ -169,12 +175,14 @@ describe('Testing fake API', () => {
|
|||||||
// Loaded icon1
|
// Loaded icon1
|
||||||
expect(loaded).to.be.eql([
|
expect(loaded).to.be.eql([
|
||||||
{
|
{
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
name: 'icon1',
|
name: 'icon1',
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
expect(pending).to.be.eql([
|
expect(pending).to.be.eql([
|
||||||
{
|
{
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
name: 'icon2',
|
name: 'icon2',
|
||||||
},
|
},
|
||||||
|
@ -46,6 +46,7 @@ describe('Testing legacy finder', () => {
|
|||||||
// Test all icons
|
// Test all icons
|
||||||
testIcon(
|
testIcon(
|
||||||
{
|
{
|
||||||
|
provider: '',
|
||||||
prefix: 'mdi',
|
prefix: 'mdi',
|
||||||
name: 'home',
|
name: 'home',
|
||||||
},
|
},
|
||||||
@ -54,6 +55,7 @@ describe('Testing legacy finder', () => {
|
|||||||
|
|
||||||
testIcon(
|
testIcon(
|
||||||
{
|
{
|
||||||
|
provider: '',
|
||||||
prefix: 'mdi',
|
prefix: 'mdi',
|
||||||
name: 'account',
|
name: 'account',
|
||||||
},
|
},
|
||||||
@ -62,6 +64,7 @@ describe('Testing legacy finder', () => {
|
|||||||
|
|
||||||
testIcon(
|
testIcon(
|
||||||
{
|
{
|
||||||
|
provider: '',
|
||||||
prefix: 'ic',
|
prefix: 'ic',
|
||||||
name: 'baseline-account',
|
name: 'baseline-account',
|
||||||
},
|
},
|
||||||
|
@ -46,6 +46,7 @@ describe('Testing finder', () => {
|
|||||||
// Test all icons
|
// Test all icons
|
||||||
testIcon(
|
testIcon(
|
||||||
{
|
{
|
||||||
|
provider: '',
|
||||||
prefix: 'mdi',
|
prefix: 'mdi',
|
||||||
name: 'home',
|
name: 'home',
|
||||||
},
|
},
|
||||||
@ -54,6 +55,7 @@ describe('Testing finder', () => {
|
|||||||
|
|
||||||
testIcon(
|
testIcon(
|
||||||
{
|
{
|
||||||
|
provider: '',
|
||||||
prefix: 'mdi',
|
prefix: 'mdi',
|
||||||
name: 'account',
|
name: 'account',
|
||||||
},
|
},
|
||||||
@ -62,6 +64,7 @@ describe('Testing finder', () => {
|
|||||||
|
|
||||||
testIcon(
|
testIcon(
|
||||||
{
|
{
|
||||||
|
provider: '',
|
||||||
prefix: 'ic',
|
prefix: 'ic',
|
||||||
name: 'baseline-account',
|
name: 'baseline-account',
|
||||||
},
|
},
|
||||||
|
@ -18,7 +18,7 @@ addFinder(iconifyFinder);
|
|||||||
|
|
||||||
describe('Testing legacy renderer', () => {
|
describe('Testing legacy renderer', () => {
|
||||||
// Add mentioned icons to storage
|
// Add mentioned icons to storage
|
||||||
const storage = getStorage('mdi');
|
const storage = getStorage('', 'mdi');
|
||||||
addIconSet(storage, {
|
addIconSet(storage, {
|
||||||
prefix: 'mdi',
|
prefix: 'mdi',
|
||||||
icons: {
|
icons: {
|
||||||
@ -82,6 +82,7 @@ describe('Testing legacy renderer', () => {
|
|||||||
|
|
||||||
// Test element
|
// Test element
|
||||||
expect(element.name).to.be.eql({
|
expect(element.name).to.be.eql({
|
||||||
|
provider: '',
|
||||||
prefix: 'mdi',
|
prefix: 'mdi',
|
||||||
name: 'account-cash',
|
name: 'account-cash',
|
||||||
});
|
});
|
||||||
@ -124,6 +125,7 @@ describe('Testing legacy renderer', () => {
|
|||||||
|
|
||||||
// Test element
|
// Test element
|
||||||
expect(element.name).to.be.eql({
|
expect(element.name).to.be.eql({
|
||||||
|
provider: '',
|
||||||
prefix: 'mdi',
|
prefix: 'mdi',
|
||||||
name: 'account',
|
name: 'account',
|
||||||
});
|
});
|
||||||
@ -167,6 +169,7 @@ describe('Testing legacy renderer', () => {
|
|||||||
|
|
||||||
// Test element
|
// Test element
|
||||||
expect(element.name).to.be.eql({
|
expect(element.name).to.be.eql({
|
||||||
|
provider: '',
|
||||||
prefix: 'mdi',
|
prefix: 'mdi',
|
||||||
name: 'account-box',
|
name: 'account-box',
|
||||||
});
|
});
|
||||||
@ -214,6 +217,7 @@ describe('Testing legacy renderer', () => {
|
|||||||
|
|
||||||
// Test element
|
// Test element
|
||||||
expect(element.name).to.be.eql({
|
expect(element.name).to.be.eql({
|
||||||
|
provider: '',
|
||||||
prefix: 'mdi',
|
prefix: 'mdi',
|
||||||
name: 'home',
|
name: 'home',
|
||||||
});
|
});
|
||||||
@ -255,6 +259,7 @@ describe('Testing legacy renderer', () => {
|
|||||||
|
|
||||||
// Test element
|
// Test element
|
||||||
expect(element.name).to.be.eql({
|
expect(element.name).to.be.eql({
|
||||||
|
provider: '',
|
||||||
prefix: 'mdi',
|
prefix: 'mdi',
|
||||||
name: 'home',
|
name: 'home',
|
||||||
});
|
});
|
||||||
@ -299,6 +304,7 @@ describe('Testing legacy renderer', () => {
|
|||||||
|
|
||||||
// Test element
|
// Test element
|
||||||
expect(element.name).to.be.eql({
|
expect(element.name).to.be.eql({
|
||||||
|
provider: '',
|
||||||
prefix: 'mdi',
|
prefix: 'mdi',
|
||||||
name: 'account',
|
name: 'account',
|
||||||
});
|
});
|
||||||
@ -372,6 +378,7 @@ describe('Testing legacy renderer', () => {
|
|||||||
|
|
||||||
// Test element
|
// Test element
|
||||||
expect(element.name).to.be.eql({
|
expect(element.name).to.be.eql({
|
||||||
|
provider: '',
|
||||||
prefix: 'mdi',
|
prefix: 'mdi',
|
||||||
name: 'home',
|
name: 'home',
|
||||||
});
|
});
|
||||||
@ -537,6 +544,7 @@ describe('Testing legacy renderer', () => {
|
|||||||
expect(element).to.not.be.eql(lastElement); // different 'element' and 'name' properties
|
expect(element).to.not.be.eql(lastElement); // different 'element' and 'name' properties
|
||||||
expect(element.name).to.not.be.eql(lastElement.name);
|
expect(element.name).to.not.be.eql(lastElement.name);
|
||||||
expect(element.name).to.be.eql({
|
expect(element.name).to.be.eql({
|
||||||
|
provider: '',
|
||||||
prefix: 'mdi',
|
prefix: 'mdi',
|
||||||
name: 'account',
|
name: 'account',
|
||||||
});
|
});
|
||||||
@ -582,6 +590,7 @@ describe('Testing legacy renderer', () => {
|
|||||||
|
|
||||||
// Test element
|
// Test element
|
||||||
expect(element.name).to.be.eql({
|
expect(element.name).to.be.eql({
|
||||||
|
provider: '',
|
||||||
prefix: 'mdi',
|
prefix: 'mdi',
|
||||||
name: 'home',
|
name: 'home',
|
||||||
});
|
});
|
||||||
@ -630,6 +639,7 @@ describe('Testing legacy renderer', () => {
|
|||||||
|
|
||||||
// Test element
|
// Test element
|
||||||
expect(element.name).to.be.eql({
|
expect(element.name).to.be.eql({
|
||||||
|
provider: '',
|
||||||
prefix: 'mdi',
|
prefix: 'mdi',
|
||||||
name: 'home',
|
name: 'home',
|
||||||
});
|
});
|
||||||
@ -676,6 +686,7 @@ describe('Testing legacy renderer', () => {
|
|||||||
|
|
||||||
// Test element
|
// Test element
|
||||||
expect(element.name).to.be.eql({
|
expect(element.name).to.be.eql({
|
||||||
|
provider: '',
|
||||||
prefix: 'mdi',
|
prefix: 'mdi',
|
||||||
name: 'home',
|
name: 'home',
|
||||||
});
|
});
|
||||||
@ -764,6 +775,7 @@ describe('Testing legacy renderer', () => {
|
|||||||
|
|
||||||
// Test element
|
// Test element
|
||||||
expect(element.name).to.be.eql({
|
expect(element.name).to.be.eql({
|
||||||
|
provider: '',
|
||||||
prefix: 'mdi',
|
prefix: 'mdi',
|
||||||
name: 'home',
|
name: 'home',
|
||||||
});
|
});
|
||||||
@ -861,6 +873,7 @@ describe('Testing legacy renderer', () => {
|
|||||||
|
|
||||||
// Test element
|
// Test element
|
||||||
expect(element.name).to.be.eql({
|
expect(element.name).to.be.eql({
|
||||||
|
provider: '',
|
||||||
prefix: 'mdi',
|
prefix: 'mdi',
|
||||||
name: 'home',
|
name: 'home',
|
||||||
});
|
});
|
||||||
@ -946,6 +959,7 @@ describe('Testing legacy renderer', () => {
|
|||||||
|
|
||||||
// Test element
|
// Test element
|
||||||
expect(element.name).to.be.eql({
|
expect(element.name).to.be.eql({
|
||||||
|
provider: '',
|
||||||
prefix: 'mdi',
|
prefix: 'mdi',
|
||||||
name: 'home',
|
name: 'home',
|
||||||
});
|
});
|
||||||
|
@ -18,7 +18,7 @@ addFinder(iconifyFinder);
|
|||||||
|
|
||||||
describe('Testing renderer', () => {
|
describe('Testing renderer', () => {
|
||||||
// Add mentioned icons to storage
|
// Add mentioned icons to storage
|
||||||
const storage = getStorage('mdi');
|
const storage = getStorage('', 'mdi');
|
||||||
addIconSet(storage, {
|
addIconSet(storage, {
|
||||||
prefix: 'mdi',
|
prefix: 'mdi',
|
||||||
icons: {
|
icons: {
|
||||||
@ -82,6 +82,7 @@ describe('Testing renderer', () => {
|
|||||||
|
|
||||||
// Test element
|
// Test element
|
||||||
expect(element.name).to.be.eql({
|
expect(element.name).to.be.eql({
|
||||||
|
provider: '',
|
||||||
prefix: 'mdi',
|
prefix: 'mdi',
|
||||||
name: 'account-cash',
|
name: 'account-cash',
|
||||||
});
|
});
|
||||||
@ -124,6 +125,7 @@ describe('Testing renderer', () => {
|
|||||||
|
|
||||||
// Test element
|
// Test element
|
||||||
expect(element.name).to.be.eql({
|
expect(element.name).to.be.eql({
|
||||||
|
provider: '',
|
||||||
prefix: 'mdi',
|
prefix: 'mdi',
|
||||||
name: 'account',
|
name: 'account',
|
||||||
});
|
});
|
||||||
@ -167,6 +169,7 @@ describe('Testing renderer', () => {
|
|||||||
|
|
||||||
// Test element
|
// Test element
|
||||||
expect(element.name).to.be.eql({
|
expect(element.name).to.be.eql({
|
||||||
|
provider: '',
|
||||||
prefix: 'mdi',
|
prefix: 'mdi',
|
||||||
name: 'account-box',
|
name: 'account-box',
|
||||||
});
|
});
|
||||||
@ -214,6 +217,7 @@ describe('Testing renderer', () => {
|
|||||||
|
|
||||||
// Test element
|
// Test element
|
||||||
expect(element.name).to.be.eql({
|
expect(element.name).to.be.eql({
|
||||||
|
provider: '',
|
||||||
prefix: 'mdi',
|
prefix: 'mdi',
|
||||||
name: 'home',
|
name: 'home',
|
||||||
});
|
});
|
||||||
@ -255,6 +259,7 @@ describe('Testing renderer', () => {
|
|||||||
|
|
||||||
// Test element
|
// Test element
|
||||||
expect(element.name).to.be.eql({
|
expect(element.name).to.be.eql({
|
||||||
|
provider: '',
|
||||||
prefix: 'mdi',
|
prefix: 'mdi',
|
||||||
name: 'home',
|
name: 'home',
|
||||||
});
|
});
|
||||||
@ -301,6 +306,7 @@ describe('Testing renderer', () => {
|
|||||||
|
|
||||||
// Test element
|
// Test element
|
||||||
expect(element.name).to.be.eql({
|
expect(element.name).to.be.eql({
|
||||||
|
provider: '',
|
||||||
prefix: 'mdi',
|
prefix: 'mdi',
|
||||||
name: 'account',
|
name: 'account',
|
||||||
});
|
});
|
||||||
@ -374,6 +380,7 @@ describe('Testing renderer', () => {
|
|||||||
|
|
||||||
// Test element
|
// Test element
|
||||||
expect(element.name).to.be.eql({
|
expect(element.name).to.be.eql({
|
||||||
|
provider: '',
|
||||||
prefix: 'mdi',
|
prefix: 'mdi',
|
||||||
name: 'home',
|
name: 'home',
|
||||||
});
|
});
|
||||||
@ -541,6 +548,7 @@ describe('Testing renderer', () => {
|
|||||||
expect(element).to.not.be.eql(lastElement); // different 'element' and 'name' properties
|
expect(element).to.not.be.eql(lastElement); // different 'element' and 'name' properties
|
||||||
expect(element.name).to.not.be.eql(lastElement.name);
|
expect(element.name).to.not.be.eql(lastElement.name);
|
||||||
expect(element.name).to.be.eql({
|
expect(element.name).to.be.eql({
|
||||||
|
provider: '',
|
||||||
prefix: 'mdi',
|
prefix: 'mdi',
|
||||||
name: 'account',
|
name: 'account',
|
||||||
});
|
});
|
||||||
@ -586,6 +594,7 @@ describe('Testing renderer', () => {
|
|||||||
|
|
||||||
// Test element
|
// Test element
|
||||||
expect(element.name).to.be.eql({
|
expect(element.name).to.be.eql({
|
||||||
|
provider: '',
|
||||||
prefix: 'mdi',
|
prefix: 'mdi',
|
||||||
name: 'home',
|
name: 'home',
|
||||||
});
|
});
|
||||||
@ -634,6 +643,7 @@ describe('Testing renderer', () => {
|
|||||||
|
|
||||||
// Test element
|
// Test element
|
||||||
expect(element.name).to.be.eql({
|
expect(element.name).to.be.eql({
|
||||||
|
provider: '',
|
||||||
prefix: 'mdi',
|
prefix: 'mdi',
|
||||||
name: 'home',
|
name: 'home',
|
||||||
});
|
});
|
||||||
@ -680,6 +690,7 @@ describe('Testing renderer', () => {
|
|||||||
|
|
||||||
// Test element
|
// Test element
|
||||||
expect(element.name).to.be.eql({
|
expect(element.name).to.be.eql({
|
||||||
|
provider: '',
|
||||||
prefix: 'mdi',
|
prefix: 'mdi',
|
||||||
name: 'home',
|
name: 'home',
|
||||||
});
|
});
|
||||||
@ -768,6 +779,7 @@ describe('Testing renderer', () => {
|
|||||||
|
|
||||||
// Test element
|
// Test element
|
||||||
expect(element.name).to.be.eql({
|
expect(element.name).to.be.eql({
|
||||||
|
provider: '',
|
||||||
prefix: 'mdi',
|
prefix: 'mdi',
|
||||||
name: 'home',
|
name: 'home',
|
||||||
});
|
});
|
||||||
@ -865,6 +877,7 @@ describe('Testing renderer', () => {
|
|||||||
|
|
||||||
// Test element
|
// Test element
|
||||||
expect(element.name).to.be.eql({
|
expect(element.name).to.be.eql({
|
||||||
|
provider: '',
|
||||||
prefix: 'mdi',
|
prefix: 'mdi',
|
||||||
name: 'home',
|
name: 'home',
|
||||||
});
|
});
|
||||||
@ -950,6 +963,7 @@ describe('Testing renderer', () => {
|
|||||||
|
|
||||||
// Test element
|
// Test element
|
||||||
expect(element.name).to.be.eql({
|
expect(element.name).to.be.eql({
|
||||||
|
provider: '',
|
||||||
prefix: 'mdi',
|
prefix: 'mdi',
|
||||||
name: 'home',
|
name: 'home',
|
||||||
});
|
});
|
||||||
|
@ -17,7 +17,7 @@ addFinder(iconifyIconFinder);
|
|||||||
|
|
||||||
describe('Scanning DOM', () => {
|
describe('Scanning DOM', () => {
|
||||||
// Add mentioned icons to storage
|
// Add mentioned icons to storage
|
||||||
const storage = getStorage('mdi');
|
const storage = getStorage('', 'mdi');
|
||||||
addIconSet(storage, {
|
addIconSet(storage, {
|
||||||
prefix: 'mdi',
|
prefix: 'mdi',
|
||||||
icons: {
|
icons: {
|
||||||
|
@ -5,7 +5,7 @@ import { getNode } from './node';
|
|||||||
import { addFinder } from '@iconify/iconify/lib/finder';
|
import { addFinder } from '@iconify/iconify/lib/finder';
|
||||||
import { FakeData, setFakeData, prepareQuery, sendQuery } from './fake-api';
|
import { FakeData, setFakeData, prepareQuery, sendQuery } from './fake-api';
|
||||||
import { API } from '@iconify/core/lib/api/';
|
import { API } from '@iconify/core/lib/api/';
|
||||||
import { setAPIModule } from '@iconify/core/lib/api/modules';
|
import { setDefaultAPIModule } from '@iconify/core/lib/api/modules';
|
||||||
import { setAPIConfig } from '@iconify/core/lib/api/config';
|
import { setAPIConfig } from '@iconify/core/lib/api/config';
|
||||||
import { coreModules } from '@iconify/core/lib/modules';
|
import { coreModules } from '@iconify/core/lib/modules';
|
||||||
import { finder as iconifyFinder } from '@iconify/iconify/lib/finders/iconify';
|
import { finder as iconifyFinder } from '@iconify/iconify/lib/finders/iconify';
|
||||||
@ -20,7 +20,7 @@ addFinder(iconifyFinder);
|
|||||||
addFinder(iconifyIconFinder);
|
addFinder(iconifyIconFinder);
|
||||||
|
|
||||||
// Set API
|
// Set API
|
||||||
setAPIModule({
|
setDefaultAPIModule({
|
||||||
prepare: prepareQuery,
|
prepare: prepareQuery,
|
||||||
send: sendQuery,
|
send: sendQuery,
|
||||||
});
|
});
|
||||||
@ -33,16 +33,14 @@ function nextPrefix(): string {
|
|||||||
|
|
||||||
describe('Scanning DOM with API', () => {
|
describe('Scanning DOM with API', () => {
|
||||||
it('Scan DOM with API', (done) => {
|
it('Scan DOM with API', (done) => {
|
||||||
|
const provider = nextPrefix();
|
||||||
const prefix1 = nextPrefix();
|
const prefix1 = nextPrefix();
|
||||||
const prefix2 = nextPrefix();
|
const prefix2 = nextPrefix();
|
||||||
|
|
||||||
// Set fake API hosts to make test reliable
|
// Set fake API hosts to make test reliable
|
||||||
setAPIConfig(
|
setAPIConfig(provider, {
|
||||||
{
|
resources: ['https://api1.local', 'https://api2.local'],
|
||||||
resources: ['https://api1.local', 'https://api2.local'],
|
});
|
||||||
},
|
|
||||||
[prefix1, prefix2]
|
|
||||||
);
|
|
||||||
|
|
||||||
// Set icons, load them with various delay
|
// Set icons, load them with various delay
|
||||||
const data1: FakeData = {
|
const data1: FakeData = {
|
||||||
@ -64,7 +62,7 @@ describe('Scanning DOM with API', () => {
|
|||||||
height: 24,
|
height: 24,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
setFakeData(prefix1, data1);
|
setFakeData(provider, prefix1, data1);
|
||||||
|
|
||||||
const data2: FakeData = {
|
const data2: FakeData = {
|
||||||
icons: ['account', 'account-box'],
|
icons: ['account', 'account-box'],
|
||||||
@ -85,24 +83,32 @@ describe('Scanning DOM with API', () => {
|
|||||||
height: 24,
|
height: 24,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
setFakeData(prefix2, data2);
|
setFakeData(provider, prefix2, data2);
|
||||||
|
|
||||||
const node = getNode('scan-dom');
|
const node = getNode('scan-dom');
|
||||||
node.innerHTML =
|
node.innerHTML =
|
||||||
'<div><p>Testing scanning DOM with API</p><ul>' +
|
'<div><p>Testing scanning DOM with API</p><ul>' +
|
||||||
'<li>Inline icons:' +
|
'<li>Inline icons:' +
|
||||||
' <span class="iconify iconify-inline" data-icon="' +
|
' <span class="iconify iconify-inline" data-icon="@' +
|
||||||
|
provider +
|
||||||
|
':' +
|
||||||
prefix1 +
|
prefix1 +
|
||||||
':home" style="color: red; box-shadow: 0 0 2px black;"></span>' +
|
':home" style="color: red; box-shadow: 0 0 2px black;"></span>' +
|
||||||
' <i class="iconify-inline test-icon iconify--mdi-account" data-icon="' +
|
' <i class="iconify-inline test-icon iconify--mdi-account" data-icon="@' +
|
||||||
|
provider +
|
||||||
|
':' +
|
||||||
prefix2 +
|
prefix2 +
|
||||||
':account" style="vertical-align: 0;" data-flip="horizontal" aria-hidden="false"></i>' +
|
':account" style="vertical-align: 0;" data-flip="horizontal" aria-hidden="false"></i>' +
|
||||||
'</li>' +
|
'</li>' +
|
||||||
'<li>Block icons:' +
|
'<li>Block icons:' +
|
||||||
' <iconify-icon data-icon="' +
|
' <iconify-icon data-icon="@' +
|
||||||
|
provider +
|
||||||
|
':' +
|
||||||
prefix1 +
|
prefix1 +
|
||||||
':account-cash" title="<Cash>!"></iconify-icon>' +
|
':account-cash" title="<Cash>!"></iconify-icon>' +
|
||||||
' <i class="iconify-icon" data-icon="' +
|
' <i class="iconify-icon" data-icon="@' +
|
||||||
|
provider +
|
||||||
|
':' +
|
||||||
prefix2 +
|
prefix2 +
|
||||||
':account-box" data-inline="true" data-rotate="2" data-width="42"></i>' +
|
':account-box" data-inline="true" data-rotate="2" data-width="42"></i>' +
|
||||||
'</li>' +
|
'</li>' +
|
||||||
@ -133,16 +139,14 @@ describe('Scanning DOM with API', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Changing icon name before it loaded', (done) => {
|
it('Changing icon name before it loaded', (done) => {
|
||||||
|
const provider = nextPrefix();
|
||||||
const prefix1 = nextPrefix();
|
const prefix1 = nextPrefix();
|
||||||
const prefix2 = nextPrefix();
|
const prefix2 = nextPrefix();
|
||||||
|
|
||||||
// Set fake API hosts to make test reliable
|
// Set fake API hosts to make test reliable
|
||||||
setAPIConfig(
|
setAPIConfig(provider, {
|
||||||
{
|
resources: ['https://api1.local', 'https://api2.local'],
|
||||||
resources: ['https://api1.local', 'https://api2.local'],
|
});
|
||||||
},
|
|
||||||
[prefix1, prefix2]
|
|
||||||
);
|
|
||||||
|
|
||||||
// Set icons, load them with various delay
|
// Set icons, load them with various delay
|
||||||
const data1: FakeData = {
|
const data1: FakeData = {
|
||||||
@ -164,7 +168,7 @@ describe('Scanning DOM with API', () => {
|
|||||||
height: 24,
|
height: 24,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
setFakeData(prefix1, data1);
|
setFakeData(provider, prefix1, data1);
|
||||||
|
|
||||||
const data2: FakeData = {
|
const data2: FakeData = {
|
||||||
icons: ['account', 'account-box'],
|
icons: ['account', 'account-box'],
|
||||||
@ -185,7 +189,7 @@ describe('Scanning DOM with API', () => {
|
|||||||
height: 24,
|
height: 24,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
setFakeData(prefix2, data2);
|
setFakeData(provider, prefix2, data2);
|
||||||
|
|
||||||
const data1b: FakeData = {
|
const data1b: FakeData = {
|
||||||
icons: ['account', 'account-box'],
|
icons: ['account', 'account-box'],
|
||||||
@ -206,24 +210,32 @@ describe('Scanning DOM with API', () => {
|
|||||||
height: 24,
|
height: 24,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
setFakeData(prefix1, data1b);
|
setFakeData(provider, prefix1, data1b);
|
||||||
|
|
||||||
const node = getNode('scan-dom');
|
const node = getNode('scan-dom');
|
||||||
node.innerHTML =
|
node.innerHTML =
|
||||||
'<div><p>Testing scanning DOM with API: renamed icon</p><ul>' +
|
'<div><p>Testing scanning DOM with API: renamed icon</p><ul>' +
|
||||||
'<li>Default finder:' +
|
'<li>Default finder:' +
|
||||||
' <span class="iconify-inline first-icon" data-icon="' +
|
' <span class="iconify-inline first-icon" data-icon="@' +
|
||||||
|
provider +
|
||||||
|
':' +
|
||||||
prefix1 +
|
prefix1 +
|
||||||
':home" style="color: red; box-shadow: 0 0 2px black;"></span>' +
|
':home" style="color: red; box-shadow: 0 0 2px black;"></span>' +
|
||||||
' <i class="iconify-inline second-icon iconify--mdi-account" data-icon="' +
|
' <i class="iconify-inline second-icon iconify--mdi-account" data-icon="@' +
|
||||||
|
provider +
|
||||||
|
':' +
|
||||||
prefix2 +
|
prefix2 +
|
||||||
':account" style="vertical-align: 0;" data-flip="horizontal" aria-hidden="false"></i>' +
|
':account" style="vertical-align: 0;" data-flip="horizontal" aria-hidden="false"></i>' +
|
||||||
'</li>' +
|
'</li>' +
|
||||||
'<li>IconifyIcon finder:' +
|
'<li>IconifyIcon finder:' +
|
||||||
' <iconify-icon class="third-icon" data-icon="' +
|
' <iconify-icon class="third-icon" data-icon="@' +
|
||||||
|
provider +
|
||||||
|
':' +
|
||||||
prefix1 +
|
prefix1 +
|
||||||
':account-cash" title="<Cash>!"></iconify-icon>' +
|
':account-cash" title="<Cash>!"></iconify-icon>' +
|
||||||
' <iconify-icon class="fourth-icon" data-icon="' +
|
' <iconify-icon class="fourth-icon" data-icon="@' +
|
||||||
|
provider +
|
||||||
|
':' +
|
||||||
prefix2 +
|
prefix2 +
|
||||||
':account-box" data-inline="true" data-rotate="2" data-width="42"></iconify-icon>' +
|
':account-box" data-inline="true" data-rotate="2" data-width="42"></iconify-icon>' +
|
||||||
'</li>' +
|
'</li>' +
|
||||||
@ -244,7 +256,10 @@ describe('Scanning DOM with API', () => {
|
|||||||
const icon = node.querySelector('iconify-icon[title]');
|
const icon = node.querySelector('iconify-icon[title]');
|
||||||
expect(icon).to.not.be.equal(null);
|
expect(icon).to.not.be.equal(null);
|
||||||
expect(icon.getAttribute('class')).to.be.equal('third-icon');
|
expect(icon.getAttribute('class')).to.be.equal('third-icon');
|
||||||
icon.setAttribute('data-icon', prefix1 + ':account');
|
icon.setAttribute(
|
||||||
|
'data-icon',
|
||||||
|
'@' + provider + ':' + prefix1 + ':account'
|
||||||
|
);
|
||||||
|
|
||||||
// First API response should have loaded, but only 1 icon should have been rendered
|
// First API response should have loaded, but only 1 icon should have been rendered
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@ -273,16 +288,14 @@ describe('Scanning DOM with API', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Changing icon name before it loaded to invalid name', (done) => {
|
it('Changing icon name before it loaded to invalid name', (done) => {
|
||||||
|
const provider = nextPrefix();
|
||||||
const prefix1 = nextPrefix();
|
const prefix1 = nextPrefix();
|
||||||
const prefix2 = nextPrefix();
|
const prefix2 = nextPrefix();
|
||||||
|
|
||||||
// Set fake API hosts to make test reliable
|
// Set fake API hosts to make test reliable
|
||||||
setAPIConfig(
|
setAPIConfig(provider, {
|
||||||
{
|
resources: ['https://api1.local', 'https://api2.local'],
|
||||||
resources: ['https://api1.local', 'https://api2.local'],
|
});
|
||||||
},
|
|
||||||
[prefix1, prefix2]
|
|
||||||
);
|
|
||||||
|
|
||||||
// Set icons, load them with various delay
|
// Set icons, load them with various delay
|
||||||
const data1: FakeData = {
|
const data1: FakeData = {
|
||||||
@ -304,7 +317,7 @@ describe('Scanning DOM with API', () => {
|
|||||||
height: 24,
|
height: 24,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
setFakeData(prefix1, data1);
|
setFakeData(provider, prefix1, data1);
|
||||||
|
|
||||||
const data2: FakeData = {
|
const data2: FakeData = {
|
||||||
icons: ['account', 'account-box'],
|
icons: ['account', 'account-box'],
|
||||||
@ -325,24 +338,32 @@ describe('Scanning DOM with API', () => {
|
|||||||
height: 24,
|
height: 24,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
setFakeData(prefix2, data2);
|
setFakeData(provider, prefix2, data2);
|
||||||
|
|
||||||
const node = getNode('scan-dom');
|
const node = getNode('scan-dom');
|
||||||
node.innerHTML =
|
node.innerHTML =
|
||||||
'<div><p>Testing scanning DOM with API: invalid name</p><ul>' +
|
'<div><p>Testing scanning DOM with API: invalid name</p><ul>' +
|
||||||
'<li>Inline icons:' +
|
'<li>Inline icons:' +
|
||||||
' <span class="iconify" data-icon="' +
|
' <span class="iconify" data-icon="@' +
|
||||||
|
provider +
|
||||||
|
':' +
|
||||||
prefix1 +
|
prefix1 +
|
||||||
':home" style="color: red; box-shadow: 0 0 2px black;"></span>' +
|
':home" style="color: red; box-shadow: 0 0 2px black;"></span>' +
|
||||||
' <i class="iconify test-icon iconify--mdi-account" data-icon="' +
|
' <i class="iconify test-icon iconify--mdi-account" data-icon="@' +
|
||||||
|
provider +
|
||||||
|
':' +
|
||||||
prefix2 +
|
prefix2 +
|
||||||
':account" style="vertical-align: 0;" data-flip="horizontal" aria-hidden="false"></i>' +
|
':account" style="vertical-align: 0;" data-flip="horizontal" aria-hidden="false"></i>' +
|
||||||
'</li>' +
|
'</li>' +
|
||||||
'<li>Block icons:' +
|
'<li>Block icons:' +
|
||||||
' <iconify-icon data-icon="' +
|
' <iconify-icon data-icon="@' +
|
||||||
|
provider +
|
||||||
|
':' +
|
||||||
prefix1 +
|
prefix1 +
|
||||||
':account-cash" title="<Cash>!"></iconify-icon>' +
|
':account-cash" title="<Cash>!"></iconify-icon>' +
|
||||||
' <iconify-icon data-icon="' +
|
' <iconify-icon data-icon="@' +
|
||||||
|
provider +
|
||||||
|
':' +
|
||||||
prefix2 +
|
prefix2 +
|
||||||
':account-box" data-inline="true" data-rotate="2" data-width="42"></iconify-icon>' +
|
':account-box" data-inline="true" data-rotate="2" data-width="42"></iconify-icon>' +
|
||||||
'</li>' +
|
'</li>' +
|
||||||
@ -355,7 +376,7 @@ describe('Scanning DOM with API', () => {
|
|||||||
// Change icon name
|
// Change icon name
|
||||||
const icon = node.querySelector('iconify-icon[title]');
|
const icon = node.querySelector('iconify-icon[title]');
|
||||||
expect(icon).to.not.be.equal(null);
|
expect(icon).to.not.be.equal(null);
|
||||||
icon.setAttribute('data-icon', 'foo');
|
icon.setAttribute('data-icon', '@' + provider + ':foo');
|
||||||
|
|
||||||
// First API response should have loaded, but only 1 icon
|
// First API response should have loaded, but only 1 icon
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
@ -19,13 +19,23 @@ export interface FakeData {
|
|||||||
/**
|
/**
|
||||||
* Fake data storage
|
* Fake data storage
|
||||||
*/
|
*/
|
||||||
const fakeData: Record<string, FakeData[]> = Object.create(null);
|
const fakeData: Record<string, Record<string, FakeData[]>> = Object.create(
|
||||||
|
null
|
||||||
|
);
|
||||||
|
|
||||||
export function setFakeData(prefix: string, item: FakeData): void {
|
export function setFakeData(
|
||||||
if (fakeData[prefix] === void 0) {
|
provider: string,
|
||||||
fakeData[prefix] = [];
|
prefix: string,
|
||||||
|
item: FakeData
|
||||||
|
): void {
|
||||||
|
if (fakeData[provider] === void 0) {
|
||||||
|
fakeData[provider] = Object.create(null);
|
||||||
}
|
}
|
||||||
fakeData[prefix].push(item);
|
const providerFakeData = fakeData[provider];
|
||||||
|
if (providerFakeData[prefix] === void 0) {
|
||||||
|
providerFakeData[prefix] = [];
|
||||||
|
}
|
||||||
|
providerFakeData[prefix].push(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
interface FakeAPIQueryParams extends APIQueryParams {
|
interface FakeAPIQueryParams extends APIQueryParams {
|
||||||
@ -36,6 +46,7 @@ interface FakeAPIQueryParams extends APIQueryParams {
|
|||||||
* Prepare params
|
* Prepare params
|
||||||
*/
|
*/
|
||||||
export const prepareQuery: IconifyAPIPrepareQuery = (
|
export const prepareQuery: IconifyAPIPrepareQuery = (
|
||||||
|
provider: string,
|
||||||
prefix: string,
|
prefix: string,
|
||||||
icons: string[]
|
icons: string[]
|
||||||
): APIQueryParams[] => {
|
): APIQueryParams[] => {
|
||||||
@ -43,10 +54,15 @@ export const prepareQuery: IconifyAPIPrepareQuery = (
|
|||||||
const items: APIQueryParams[] = [];
|
const items: APIQueryParams[] = [];
|
||||||
let missing = icons.slice(0);
|
let missing = icons.slice(0);
|
||||||
|
|
||||||
if (fakeData[prefix] !== void 0) {
|
if (fakeData[provider] === void 0) {
|
||||||
fakeData[prefix].forEach(item => {
|
fakeData[provider] = Object.create(null);
|
||||||
|
}
|
||||||
|
const providerFakeData = fakeData[provider];
|
||||||
|
|
||||||
|
if (providerFakeData[prefix] !== void 0) {
|
||||||
|
providerFakeData[prefix].forEach((item) => {
|
||||||
const matches = item.icons.filter(
|
const matches = item.icons.filter(
|
||||||
icon => missing.indexOf(icon) !== -1
|
(icon) => missing.indexOf(icon) !== -1
|
||||||
);
|
);
|
||||||
if (!matches.length) {
|
if (!matches.length) {
|
||||||
// No match
|
// No match
|
||||||
@ -54,8 +70,9 @@ export const prepareQuery: IconifyAPIPrepareQuery = (
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Contains at least one matching icon
|
// Contains at least one matching icon
|
||||||
missing = missing.filter(icon => matches.indexOf(icon) === -1);
|
missing = missing.filter((icon) => matches.indexOf(icon) === -1);
|
||||||
const query: FakeAPIQueryParams = {
|
const query: FakeAPIQueryParams = {
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
icons: matches,
|
icons: matches,
|
||||||
data: item,
|
data: item,
|
||||||
@ -75,6 +92,7 @@ export const sendQuery: IconifyAPISendQuery = (
|
|||||||
params: APIQueryParams,
|
params: APIQueryParams,
|
||||||
status: RedundancyPendingItem
|
status: RedundancyPendingItem
|
||||||
): void => {
|
): void => {
|
||||||
|
const provider = params.provider;
|
||||||
const prefix = params.prefix;
|
const prefix = params.prefix;
|
||||||
const icons = params.icons;
|
const icons = params.icons;
|
||||||
|
|
||||||
@ -88,7 +106,13 @@ export const sendQuery: IconifyAPISendQuery = (
|
|||||||
}
|
}
|
||||||
|
|
||||||
const sendResponse = () => {
|
const sendResponse = () => {
|
||||||
console.log('Sending data for prefix "' + prefix + '", icons:', icons);
|
console.log(
|
||||||
|
'Sending data for prefix "' +
|
||||||
|
(provider === '' ? '' : '@' + provider + ':') +
|
||||||
|
prefix +
|
||||||
|
'", icons:',
|
||||||
|
icons
|
||||||
|
);
|
||||||
status.done(data.data);
|
status.done(data.data);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import {
|
|||||||
} from '../interfaces/loader';
|
} from '../interfaces/loader';
|
||||||
import { getStorage } from '../storage';
|
import { getStorage } from '../storage';
|
||||||
import { SortedIcons } from '../icon/sort';
|
import { SortedIcons } from '../icon/sort';
|
||||||
|
import { IconifyIconSource } from '../icon/name';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Storage for callbacks
|
* Storage for callbacks
|
||||||
@ -22,49 +23,70 @@ interface CallbackItem {
|
|||||||
abort: IconifyIconLoaderAbort;
|
abort: IconifyIconLoaderAbort;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Records sorted by provider and prefix
|
||||||
// This export is only for unit testing, should not be used
|
// This export is only for unit testing, should not be used
|
||||||
export const callbacks: Record<string, CallbackItem[]> = Object.create(null);
|
export const callbacks: Record<
|
||||||
const pendingUpdates: Record<string, boolean> = Object.create(null);
|
string,
|
||||||
|
Record<string, CallbackItem[]>
|
||||||
|
> = Object.create(null);
|
||||||
|
const pendingUpdates: Record<string, Record<string, boolean>> = Object.create(
|
||||||
|
null
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove callback
|
* Remove callback
|
||||||
*/
|
*/
|
||||||
function removeCallback(prefixes: string[], id: number): void {
|
function removeCallback(sources: IconifyIconSource[], id: number): void {
|
||||||
prefixes.forEach(prefix => {
|
sources.forEach((source) => {
|
||||||
const items = callbacks[prefix];
|
const provider = source.provider;
|
||||||
|
if (callbacks[provider] === void 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const providerCallbacks = callbacks[provider];
|
||||||
|
|
||||||
|
const prefix = source.prefix;
|
||||||
|
const items = providerCallbacks[prefix];
|
||||||
if (items) {
|
if (items) {
|
||||||
callbacks[prefix] = items.filter(row => row.id !== id);
|
providerCallbacks[prefix] = items.filter((row) => row.id !== id);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update all callbacks for prefix
|
* Update all callbacks for provider and prefix
|
||||||
*/
|
*/
|
||||||
export function updateCallbacks(prefix: string): void {
|
export function updateCallbacks(provider: string, prefix: string): void {
|
||||||
if (!pendingUpdates[prefix]) {
|
if (pendingUpdates[provider] === void 0) {
|
||||||
pendingUpdates[prefix] = true;
|
pendingUpdates[provider] = Object.create(null);
|
||||||
setTimeout(() => {
|
}
|
||||||
pendingUpdates[prefix] = false;
|
const providerPendingUpdates = pendingUpdates[provider];
|
||||||
|
|
||||||
if (callbacks[prefix] === void 0) {
|
if (!providerPendingUpdates[prefix]) {
|
||||||
|
providerPendingUpdates[prefix] = true;
|
||||||
|
setTimeout(() => {
|
||||||
|
providerPendingUpdates[prefix] = false;
|
||||||
|
|
||||||
|
if (
|
||||||
|
callbacks[provider] === void 0 ||
|
||||||
|
callbacks[provider][prefix] === void 0
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get all items
|
// Get all items
|
||||||
const items = callbacks[prefix].slice(0);
|
const items = callbacks[provider][prefix].slice(0);
|
||||||
if (!items.length) {
|
if (!items.length) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const storage = getStorage(prefix);
|
const storage = getStorage(provider, prefix);
|
||||||
|
|
||||||
// Check each item for changes
|
// Check each item for changes
|
||||||
let hasPending = false;
|
let hasPending = false;
|
||||||
items.forEach((item: CallbackItem) => {
|
items.forEach((item: CallbackItem) => {
|
||||||
const icons = item.icons;
|
const icons = item.icons;
|
||||||
const oldLength = icons.pending.length;
|
const oldLength = icons.pending.length;
|
||||||
icons.pending = icons.pending.filter(icon => {
|
icons.pending = icons.pending.filter((icon) => {
|
||||||
if (icon.prefix !== prefix) {
|
if (icon.prefix !== prefix) {
|
||||||
// Checking only current prefix
|
// Checking only current prefix
|
||||||
return true;
|
return true;
|
||||||
@ -74,12 +96,14 @@ export function updateCallbacks(prefix: string): void {
|
|||||||
if (storage.icons[name] !== void 0) {
|
if (storage.icons[name] !== void 0) {
|
||||||
// Loaded
|
// Loaded
|
||||||
icons.loaded.push({
|
icons.loaded.push({
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
name,
|
name,
|
||||||
});
|
});
|
||||||
} else if (storage.missing[name] !== void 0) {
|
} else if (storage.missing[name] !== void 0) {
|
||||||
// Missing
|
// Missing
|
||||||
icons.missing.push({
|
icons.missing.push({
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
name,
|
name,
|
||||||
});
|
});
|
||||||
@ -96,7 +120,15 @@ export function updateCallbacks(prefix: string): void {
|
|||||||
if (icons.pending.length !== oldLength) {
|
if (icons.pending.length !== oldLength) {
|
||||||
if (!hasPending) {
|
if (!hasPending) {
|
||||||
// All icons have been loaded - remove callback from prefix
|
// All icons have been loaded - remove callback from prefix
|
||||||
removeCallback([prefix], item.id);
|
removeCallback(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
provider,
|
||||||
|
prefix,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
item.id
|
||||||
|
);
|
||||||
}
|
}
|
||||||
item.callback(
|
item.callback(
|
||||||
icons.loaded.slice(0),
|
icons.loaded.slice(0),
|
||||||
@ -121,11 +153,11 @@ let idCounter = 0;
|
|||||||
export function storeCallback(
|
export function storeCallback(
|
||||||
callback: IconifyIconLoaderCallback,
|
callback: IconifyIconLoaderCallback,
|
||||||
icons: SortedIcons,
|
icons: SortedIcons,
|
||||||
pendingPrefixes: string[]
|
pendingSources: IconifyIconSource[]
|
||||||
): IconifyIconLoaderAbort {
|
): IconifyIconLoaderAbort {
|
||||||
// Create unique id and abort function
|
// Create unique id and abort function
|
||||||
const id = idCounter++;
|
const id = idCounter++;
|
||||||
const abort = removeCallback.bind(null, pendingPrefixes, id);
|
const abort = removeCallback.bind(null, pendingSources, id);
|
||||||
|
|
||||||
if (!icons.pending.length) {
|
if (!icons.pending.length) {
|
||||||
// Do not store item without pending icons and return function that does nothing
|
// Do not store item without pending icons and return function that does nothing
|
||||||
@ -140,11 +172,17 @@ export function storeCallback(
|
|||||||
abort: abort,
|
abort: abort,
|
||||||
};
|
};
|
||||||
|
|
||||||
pendingPrefixes.forEach(prefix => {
|
pendingSources.forEach((source) => {
|
||||||
if (callbacks[prefix] === void 0) {
|
const provider = source.provider;
|
||||||
callbacks[prefix] = [];
|
const prefix = source.prefix;
|
||||||
|
if (callbacks[provider] === void 0) {
|
||||||
|
callbacks[provider] = Object.create(null);
|
||||||
}
|
}
|
||||||
callbacks[prefix].push(item);
|
const providerCallbacks = callbacks[provider];
|
||||||
|
if (providerCallbacks[prefix] === void 0) {
|
||||||
|
providerCallbacks[prefix] = [];
|
||||||
|
}
|
||||||
|
providerCallbacks[prefix].push(item);
|
||||||
});
|
});
|
||||||
|
|
||||||
return abort;
|
return abort;
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { RedundancyConfig } from '@cyberalien/redundancy';
|
import { RedundancyConfig } from '@cyberalien/redundancy';
|
||||||
import { merge } from '../misc/merge';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* API config
|
* API config
|
||||||
@ -12,17 +11,52 @@ export interface IconifyAPIConfig extends RedundancyConfig {
|
|||||||
maxURL: number;
|
maxURL: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
export type PartialIconifyAPIConfig = Partial<IconifyAPIConfig>;
|
||||||
* Local storage interfaces
|
|
||||||
*/
|
|
||||||
interface ConfigStorage {
|
|
||||||
// API configuration for all prefixes
|
|
||||||
default: IconifyAPIConfig;
|
|
||||||
|
|
||||||
// Prefix specific API configuration
|
/**
|
||||||
prefixes: Record<string, IconifyAPIConfig>;
|
* Create full API configuration from partial data
|
||||||
|
*/
|
||||||
|
function createConfig(
|
||||||
|
source: PartialIconifyAPIConfig
|
||||||
|
): IconifyAPIConfig | null {
|
||||||
|
if (!source.resources) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const result: IconifyAPIConfig = {
|
||||||
|
// API hosts
|
||||||
|
resources: source.resources,
|
||||||
|
|
||||||
|
// Root path
|
||||||
|
path: source.path === void 0 ? '/' : source.path,
|
||||||
|
|
||||||
|
// URL length limit
|
||||||
|
maxURL: source.maxURL ? source.maxURL : 500,
|
||||||
|
|
||||||
|
// Timeout before next host is used.
|
||||||
|
rotate: source.rotate ? source.rotate : 750,
|
||||||
|
|
||||||
|
// Timeout to retry same host.
|
||||||
|
timeout: source.timeout ? source.timeout : 5000,
|
||||||
|
|
||||||
|
// Number of attempts for each host.
|
||||||
|
limit: source.limit ? source.limit : 2,
|
||||||
|
|
||||||
|
// Randomise default API end point.
|
||||||
|
random: source.random === true,
|
||||||
|
|
||||||
|
// Start index
|
||||||
|
index: source.index ? source.index : 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Local storage
|
||||||
|
*/
|
||||||
|
const configStorage: Record<string, IconifyAPIConfig> = Object.create(null);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Redundancy for API servers.
|
* Redundancy for API servers.
|
||||||
*
|
*
|
||||||
@ -58,70 +92,28 @@ while (fallBackAPISources.length > 0) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// Add default API
|
||||||
* Default configuration
|
configStorage[''] = createConfig({
|
||||||
*/
|
|
||||||
const defaultConfig: IconifyAPIConfig = {
|
|
||||||
// API hosts
|
|
||||||
resources: ['https://api.iconify.design'].concat(fallBackAPI),
|
resources: ['https://api.iconify.design'].concat(fallBackAPI),
|
||||||
|
}) as IconifyAPIConfig;
|
||||||
// Root path
|
|
||||||
path: '/',
|
|
||||||
|
|
||||||
// URL length limit
|
|
||||||
maxURL: 500,
|
|
||||||
|
|
||||||
// Timeout before next host is used.
|
|
||||||
rotate: 750,
|
|
||||||
|
|
||||||
// Timeout to retry same host.
|
|
||||||
timeout: 5000,
|
|
||||||
|
|
||||||
// Number of attempts for each host.
|
|
||||||
limit: 2,
|
|
||||||
|
|
||||||
// Randomise default API end point.
|
|
||||||
random: false,
|
|
||||||
|
|
||||||
// Start index
|
|
||||||
index: 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Local storage
|
* Add custom config for provider
|
||||||
*/
|
|
||||||
const configStorage: ConfigStorage = {
|
|
||||||
default: defaultConfig,
|
|
||||||
prefixes: Object.create(null),
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add custom config for prefix(es)
|
|
||||||
*
|
|
||||||
* This function should be used before any API queries.
|
|
||||||
* On first API query computed configuration will be cached, so changes to config will not take effect.
|
|
||||||
*/
|
*/
|
||||||
export function setAPIConfig(
|
export function setAPIConfig(
|
||||||
customConfig: Partial<IconifyAPIConfig>,
|
provider: string,
|
||||||
prefix?: string | string[]
|
customConfig: PartialIconifyAPIConfig
|
||||||
): void {
|
): void {
|
||||||
const mergedConfig = merge(
|
const config = createConfig(customConfig);
|
||||||
configStorage.default,
|
if (config === null) {
|
||||||
customConfig
|
|
||||||
) as IconifyAPIConfig;
|
|
||||||
if (prefix === void 0) {
|
|
||||||
configStorage.default = mergedConfig;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
(typeof prefix === 'string' ? [prefix] : prefix).forEach(prefix => {
|
configStorage[provider] = config;
|
||||||
configStorage.prefixes[prefix] = mergedConfig;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get API configuration
|
* Get API configuration
|
||||||
*/
|
*/
|
||||||
export function getAPIConfig(prefix: string): IconifyAPIConfig | null {
|
export function getAPIConfig(provider: string): IconifyAPIConfig | undefined {
|
||||||
const value = configStorage.prefixes[prefix];
|
return configStorage[provider];
|
||||||
return value === void 0 ? configStorage.default : value;
|
|
||||||
}
|
}
|
||||||
|
@ -15,8 +15,8 @@ import { getAPIModule } from './modules';
|
|||||||
import { getAPIConfig, IconifyAPIConfig } from './config';
|
import { getAPIConfig, IconifyAPIConfig } from './config';
|
||||||
import { getStorage, addIconSet } from '../storage';
|
import { getStorage, addIconSet } from '../storage';
|
||||||
import { coreModules } from '../modules';
|
import { coreModules } from '../modules';
|
||||||
import { IconifyIconName } from '../icon/name';
|
import { IconifyIconName, IconifyIconSource } from '../icon/name';
|
||||||
import { listToIcons, getPrefixes } from '../icon/list';
|
import { listToIcons } from '../icon/list';
|
||||||
import { IconifyJSON } from '@iconify/types';
|
import { IconifyJSON } from '@iconify/types';
|
||||||
|
|
||||||
// Empty abort callback for loadIcons()
|
// Empty abort callback for loadIcons()
|
||||||
@ -32,10 +32,13 @@ function emptyCallback(): void {
|
|||||||
* either an icon or a missing icon. This way same icon should
|
* either an icon or a missing icon. This way same icon should
|
||||||
* never be requested twice.
|
* never be requested twice.
|
||||||
*
|
*
|
||||||
* [prefix][icon] = time when icon was added to queue
|
* [provider][prefix][icon] = time when icon was added to queue
|
||||||
*/
|
*/
|
||||||
type PendingIcons = Record<string, number>;
|
type PendingIcons = Record<string, number>;
|
||||||
const pendingIcons: Record<string, PendingIcons> = Object.create(null);
|
const pendingIcons: Record<
|
||||||
|
string,
|
||||||
|
Record<string, PendingIcons>
|
||||||
|
> = Object.create(null);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of icons that are waiting to be loaded.
|
* List of icons that are waiting to be loaded.
|
||||||
@ -45,31 +48,39 @@ const pendingIcons: Record<string, PendingIcons> = Object.create(null);
|
|||||||
* This list should not be used for any checks, use pendingIcons to check
|
* This list should not be used for any checks, use pendingIcons to check
|
||||||
* if icons is being loaded.
|
* if icons is being loaded.
|
||||||
*
|
*
|
||||||
* [prefix] = array of icon names
|
* [provider][prefix] = array of icon names
|
||||||
*/
|
*/
|
||||||
const iconsToLoad: Record<string, string[]> = Object.create(null);
|
const iconsToLoad: Record<string, Record<string, string[]>> = Object.create(
|
||||||
|
null
|
||||||
|
);
|
||||||
|
|
||||||
// Flags to merge multiple synchronous icon requests in one asynchronous request
|
// Flags to merge multiple synchronous icon requests in one asynchronous request
|
||||||
const loaderFlags: Record<string, boolean> = Object.create(null);
|
const loaderFlags: Record<string, Record<string, boolean>> = Object.create(
|
||||||
const queueFlags: Record<string, boolean> = Object.create(null);
|
null
|
||||||
|
);
|
||||||
|
const queueFlags: Record<string, Record<string, boolean>> = Object.create(null);
|
||||||
|
|
||||||
// Redundancy instances cache
|
// Redundancy instances cache, sorted by provider
|
||||||
interface LocalCache {
|
interface LocalCache {
|
||||||
config: IconifyAPIConfig | null;
|
config: IconifyAPIConfig;
|
||||||
redundancy: Redundancy | null;
|
redundancy: Redundancy;
|
||||||
}
|
}
|
||||||
const redundancyCache: Record<string, LocalCache> = Object.create(null);
|
const redundancyCache: Record<string, LocalCache> = Object.create(null);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function called when new icons have been loaded
|
* Function called when new icons have been loaded
|
||||||
*/
|
*/
|
||||||
function loadedNewIcons(prefix: string): void {
|
function loadedNewIcons(provider: string, prefix: string): void {
|
||||||
// Run only once per tick, possibly joining multiple API responses in one call
|
// Run only once per tick, possibly joining multiple API responses in one call
|
||||||
if (!loaderFlags[prefix]) {
|
if (loaderFlags[provider] === void 0) {
|
||||||
loaderFlags[prefix] = true;
|
loaderFlags[provider] = Object.create(null);
|
||||||
|
}
|
||||||
|
const providerLoaderFlags = loaderFlags[provider];
|
||||||
|
if (!providerLoaderFlags[prefix]) {
|
||||||
|
providerLoaderFlags[prefix] = true;
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
loaderFlags[prefix] = false;
|
providerLoaderFlags[prefix] = false;
|
||||||
updateCallbacks(prefix);
|
updateCallbacks(provider, prefix);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -77,7 +88,7 @@ function loadedNewIcons(prefix: string): void {
|
|||||||
/**
|
/**
|
||||||
* Load icons
|
* Load icons
|
||||||
*/
|
*/
|
||||||
function loadNewIcons(prefix: string, icons: string[]): void {
|
function loadNewIcons(provider: string, prefix: string, icons: string[]): void {
|
||||||
function err(): void {
|
function err(): void {
|
||||||
console.error(
|
console.error(
|
||||||
'Unable to retrieve icons for prefix "' +
|
'Unable to retrieve icons for prefix "' +
|
||||||
@ -86,68 +97,82 @@ function loadNewIcons(prefix: string, icons: string[]): void {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create nested objects if needed
|
||||||
|
if (iconsToLoad[provider] === void 0) {
|
||||||
|
iconsToLoad[provider] = Object.create(null);
|
||||||
|
}
|
||||||
|
const providerIconsToLoad = iconsToLoad[provider];
|
||||||
|
|
||||||
|
if (queueFlags[provider] === void 0) {
|
||||||
|
queueFlags[provider] = Object.create(null);
|
||||||
|
}
|
||||||
|
const providerQueueFlags = queueFlags[provider];
|
||||||
|
|
||||||
|
if (pendingIcons[provider] === void 0) {
|
||||||
|
pendingIcons[provider] = Object.create(null);
|
||||||
|
}
|
||||||
|
const providerPendingIcons = pendingIcons[provider];
|
||||||
|
|
||||||
// Add icons to queue
|
// Add icons to queue
|
||||||
if (iconsToLoad[prefix] === void 0) {
|
if (providerIconsToLoad[prefix] === void 0) {
|
||||||
iconsToLoad[prefix] = icons;
|
providerIconsToLoad[prefix] = icons;
|
||||||
} else {
|
} else {
|
||||||
iconsToLoad[prefix] = iconsToLoad[prefix].concat(icons).sort();
|
providerIconsToLoad[prefix] = providerIconsToLoad[prefix]
|
||||||
|
.concat(icons)
|
||||||
|
.sort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Redundancy item
|
||||||
|
let cachedReundancy: LocalCache;
|
||||||
|
|
||||||
// Trigger update on next tick, mering multiple synchronous requests into one asynchronous request
|
// Trigger update on next tick, mering multiple synchronous requests into one asynchronous request
|
||||||
if (!queueFlags[prefix]) {
|
if (!providerQueueFlags[prefix]) {
|
||||||
queueFlags[prefix] = true;
|
providerQueueFlags[prefix] = true;
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
queueFlags[prefix] = false;
|
providerQueueFlags[prefix] = false;
|
||||||
|
|
||||||
// Get icons and delete queue
|
// Get icons and delete queue
|
||||||
const icons = iconsToLoad[prefix];
|
const icons = providerIconsToLoad[prefix];
|
||||||
delete iconsToLoad[prefix];
|
delete providerIconsToLoad[prefix];
|
||||||
|
|
||||||
// Get API module
|
// Get API module
|
||||||
const api = getAPIModule(prefix);
|
const api = getAPIModule(provider);
|
||||||
if (!api) {
|
if (!api) {
|
||||||
// No way to load icons!
|
// No way to load icons!
|
||||||
err();
|
err();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get Redundancy instance
|
// Get API config and Redundancy instance
|
||||||
if (redundancyCache[prefix] === void 0) {
|
if (cachedReundancy === void 0) {
|
||||||
const config = getAPIConfig(prefix);
|
if (redundancyCache[provider] === void 0) {
|
||||||
|
const config = getAPIConfig(provider);
|
||||||
// Attempt to find matching instance from other prefixes
|
if (!config) {
|
||||||
// Using same Redundancy instance allows keeping track of failed hosts for multiple prefixes
|
// No way to load icons because configuration is not set!
|
||||||
for (const prefix2 in redundancyCache) {
|
err();
|
||||||
const item = redundancyCache[prefix2];
|
return;
|
||||||
if (item.config === config) {
|
|
||||||
redundancyCache[prefix] = item;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (redundancyCache[prefix] === void 0) {
|
const redundancy = initRedundancy(config);
|
||||||
redundancyCache[prefix] = {
|
cachedReundancy = {
|
||||||
config,
|
config,
|
||||||
redundancy: config ? initRedundancy(config) : null,
|
redundancy,
|
||||||
};
|
};
|
||||||
|
redundancyCache[provider] = cachedReundancy;
|
||||||
|
} else {
|
||||||
|
cachedReundancy = redundancyCache[provider];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const redundancy = redundancyCache[prefix].redundancy;
|
|
||||||
if (!redundancy) {
|
|
||||||
// No way to load icons because configuration is not set!
|
|
||||||
err();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare parameters and run queries
|
// Prepare parameters and run queries
|
||||||
const params = api.prepare(prefix, icons);
|
const params = api.prepare(provider, prefix, icons);
|
||||||
params.forEach((item) => {
|
params.forEach((item) => {
|
||||||
redundancy.query(
|
cachedReundancy.redundancy.query(
|
||||||
item,
|
item,
|
||||||
api.send as RedundancyQueryCallback,
|
api.send as RedundancyQueryCallback,
|
||||||
(data) => {
|
(data) => {
|
||||||
// Add icons to storage
|
// Add icons to storage
|
||||||
const storage = getStorage(prefix);
|
const storage = getStorage(provider, prefix);
|
||||||
try {
|
try {
|
||||||
const added = addIconSet(
|
const added = addIconSet(
|
||||||
storage,
|
storage,
|
||||||
@ -159,21 +184,24 @@ function loadNewIcons(prefix: string, icons: string[]): void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Remove added icons from pending list
|
// Remove added icons from pending list
|
||||||
const pending = pendingIcons[prefix];
|
const pending = providerPendingIcons[prefix];
|
||||||
added.forEach((name) => {
|
added.forEach((name) => {
|
||||||
delete pending[name];
|
delete pending[name];
|
||||||
});
|
});
|
||||||
|
|
||||||
// Cache API response
|
// Cache API response
|
||||||
if (coreModules.cache) {
|
if (coreModules.cache) {
|
||||||
coreModules.cache(data as IconifyJSON);
|
coreModules.cache(
|
||||||
|
provider,
|
||||||
|
data as IconifyJSON
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Trigger update on next tick
|
// Trigger update on next tick
|
||||||
loadedNewIcons(prefix);
|
loadedNewIcons(provider, prefix);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -184,9 +212,11 @@ function loadNewIcons(prefix: string, icons: string[]): void {
|
|||||||
/**
|
/**
|
||||||
* Check if icon is being loaded
|
* Check if icon is being loaded
|
||||||
*/
|
*/
|
||||||
const isPending: IsPending = (prefix: string, icon: string): boolean => {
|
const isPending: IsPending = (icon: IconifyIconName): boolean => {
|
||||||
return (
|
return (
|
||||||
pendingIcons[prefix] !== void 0 && pendingIcons[prefix][icon] !== void 0
|
pendingIcons[icon.provider] !== void 0 &&
|
||||||
|
pendingIcons[icon.provider][icon.prefix] !== void 0 &&
|
||||||
|
pendingIcons[icon.provider][icon.prefix][icon.name] !== void 0
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -225,16 +255,42 @@ const loadIcons: IconifyLoadIcons = (
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get all prefixes
|
// Get all sources for pending icons
|
||||||
const prefixes = getPrefixes(sortedIcons.pending);
|
const newIcons: Record<string, Record<string, string[]>> = Object.create(
|
||||||
|
null
|
||||||
|
);
|
||||||
|
const sources: IconifyIconSource[] = [];
|
||||||
|
let lastProvider: string, lastPrefix: string;
|
||||||
|
|
||||||
// Get pending icons queue for prefix and create new icons list
|
sortedIcons.pending.forEach((icon) => {
|
||||||
const newIcons: Record<string, string[]> = Object.create(null);
|
const provider = icon.provider;
|
||||||
prefixes.forEach((prefix) => {
|
const prefix = icon.prefix;
|
||||||
if (pendingIcons[prefix] === void 0) {
|
if (prefix === lastPrefix && provider === lastProvider) {
|
||||||
pendingIcons[prefix] = Object.create(null);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lastProvider = provider;
|
||||||
|
lastPrefix = prefix;
|
||||||
|
sources.push({
|
||||||
|
provider,
|
||||||
|
prefix,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (pendingIcons[provider] === void 0) {
|
||||||
|
pendingIcons[provider] = Object.create(null);
|
||||||
|
}
|
||||||
|
const providerPendingIcons = pendingIcons[provider];
|
||||||
|
if (providerPendingIcons[prefix] === void 0) {
|
||||||
|
providerPendingIcons[prefix] = Object.create(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newIcons[provider] === void 0) {
|
||||||
|
newIcons[provider] = Object.create(null);
|
||||||
|
}
|
||||||
|
const providerNewIcons = newIcons[provider];
|
||||||
|
if (providerNewIcons[prefix] === void 0) {
|
||||||
|
providerNewIcons[prefix] = [];
|
||||||
}
|
}
|
||||||
newIcons[prefix] = [];
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// List of new icons
|
// List of new icons
|
||||||
@ -244,29 +300,32 @@ const loadIcons: IconifyLoadIcons = (
|
|||||||
// If icon was called before, it must exist in pendingIcons or storage, but because this
|
// If icon was called before, it must exist in pendingIcons or storage, but because this
|
||||||
// function is called right after sortIcons() that checks storage, icon is definitely not in storage.
|
// function is called right after sortIcons() that checks storage, icon is definitely not in storage.
|
||||||
sortedIcons.pending.forEach((icon) => {
|
sortedIcons.pending.forEach((icon) => {
|
||||||
|
const provider = icon.provider;
|
||||||
const prefix = icon.prefix;
|
const prefix = icon.prefix;
|
||||||
const name = icon.name;
|
const name = icon.name;
|
||||||
|
|
||||||
const pendingQueue = pendingIcons[prefix];
|
const pendingQueue = pendingIcons[provider][prefix];
|
||||||
if (pendingQueue[name] === void 0) {
|
if (pendingQueue[name] === void 0) {
|
||||||
// New icon - add to pending queue to mark it as being loaded
|
// New icon - add to pending queue to mark it as being loaded
|
||||||
pendingQueue[name] = time;
|
pendingQueue[name] = time;
|
||||||
// Add it to new icons list to pass it to API module for loading
|
// Add it to new icons list to pass it to API module for loading
|
||||||
newIcons[prefix].push(name);
|
newIcons[provider][prefix].push(name);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Load icons on next tick to make sure result is not returned before callback is stored and
|
// Load icons on next tick to make sure result is not returned before callback is stored and
|
||||||
// to consolidate multiple synchronous loadIcons() calls into one asynchronous API call
|
// to consolidate multiple synchronous loadIcons() calls into one asynchronous API call
|
||||||
prefixes.forEach((prefix) => {
|
sources.forEach((source) => {
|
||||||
if (newIcons[prefix].length) {
|
const provider = source.provider;
|
||||||
loadNewIcons(prefix, newIcons[prefix]);
|
const prefix = source.prefix;
|
||||||
|
if (newIcons[provider][prefix].length) {
|
||||||
|
loadNewIcons(provider, prefix, newIcons[provider][prefix]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Store callback and return abort function
|
// Store callback and return abort function
|
||||||
return callback
|
return callback
|
||||||
? storeCallback(callback, sortedIcons, prefixes)
|
? storeCallback(callback, sortedIcons, sources)
|
||||||
: emptyCallback;
|
: emptyCallback;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import { RedundancyPendingItem } from '@cyberalien/redundancy';
|
|||||||
* Params for sendQuery()
|
* Params for sendQuery()
|
||||||
*/
|
*/
|
||||||
export interface APIQueryParams {
|
export interface APIQueryParams {
|
||||||
|
provider: string;
|
||||||
prefix: string;
|
prefix: string;
|
||||||
icons: string[];
|
icons: string[];
|
||||||
}
|
}
|
||||||
@ -12,6 +13,7 @@ export interface APIQueryParams {
|
|||||||
* Functions to implement in module
|
* Functions to implement in module
|
||||||
*/
|
*/
|
||||||
export type IconifyAPIPrepareQuery = (
|
export type IconifyAPIPrepareQuery = (
|
||||||
|
provider: string,
|
||||||
prefix: string,
|
prefix: string,
|
||||||
icons: string[]
|
icons: string[]
|
||||||
) => APIQueryParams[];
|
) => APIQueryParams[];
|
||||||
@ -33,43 +35,36 @@ export interface IconifyAPIModule {
|
|||||||
/**
|
/**
|
||||||
* Local storate types and entries
|
* Local storate types and entries
|
||||||
*/
|
*/
|
||||||
interface ModuleStorage {
|
interface ModulesStorage {
|
||||||
default: IconifyAPIModule | null;
|
default?: IconifyAPIModule;
|
||||||
prefixes: Record<string, IconifyAPIModule>;
|
providers: Record<string, IconifyAPIModule>;
|
||||||
}
|
}
|
||||||
|
const storage: ModulesStorage = {
|
||||||
const storage: ModuleStorage = {
|
providers: Object.create(null),
|
||||||
default: null,
|
|
||||||
prefixes: Object.create(null),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set API module
|
* Set default API module
|
||||||
*
|
|
||||||
* If prefix is not set, function sets default method.
|
|
||||||
* If prefix is a string or array of strings, function sets method only for those prefixes.
|
|
||||||
*
|
|
||||||
* This should be used before sending any API requests. If used after sending API request, method
|
|
||||||
* is already cached so changing callback will not have any effect.
|
|
||||||
*/
|
*/
|
||||||
export function setAPIModule(
|
export function setDefaultAPIModule(item: IconifyAPIModule): void {
|
||||||
item: IconifyAPIModule,
|
storage.default = item;
|
||||||
prefix?: string | string[]
|
}
|
||||||
): void {
|
|
||||||
if (prefix === void 0) {
|
|
||||||
storage.default = item;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
(typeof prefix === 'string' ? [prefix] : prefix).forEach(prefix => {
|
/**
|
||||||
storage.prefixes[prefix] = item;
|
* Set API module
|
||||||
});
|
*/
|
||||||
|
export function setProviderAPIModule(
|
||||||
|
provider: string,
|
||||||
|
item: IconifyAPIModule
|
||||||
|
): void {
|
||||||
|
storage.providers[provider] = item;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get API module
|
* Get API module
|
||||||
*/
|
*/
|
||||||
export function getAPIModule(prefix: string): IconifyAPIModule | null {
|
export function getAPIModule(provider: string): IconifyAPIModule | undefined {
|
||||||
const value = storage.prefixes[prefix];
|
return storage.providers[provider] === void 0
|
||||||
return value === void 0 ? storage.default : value;
|
? storage.default
|
||||||
|
: storage.providers[provider];
|
||||||
}
|
}
|
||||||
|
13
packages/core/src/cache/storage.ts
vendored
13
packages/core/src/cache/storage.ts
vendored
@ -13,13 +13,14 @@ type StorageEmptyList = StorageType<number[]>;
|
|||||||
|
|
||||||
export interface StoredItem {
|
export interface StoredItem {
|
||||||
cached: number;
|
cached: number;
|
||||||
|
provider: string;
|
||||||
data: IconifyJSON;
|
data: IconifyJSON;
|
||||||
}
|
}
|
||||||
|
|
||||||
// After changing configuration change it in tests/*/fake_cache.ts
|
// After changing configuration change it in tests/*/fake_cache.ts
|
||||||
|
|
||||||
// Cache version. Bump when structure changes
|
// Cache version. Bump when structure changes
|
||||||
const cacheVersion = 'iconify1';
|
const cacheVersion = 'iconify2';
|
||||||
|
|
||||||
// Cache keys
|
// Cache keys
|
||||||
const cachePrefix = 'iconify';
|
const cachePrefix = 'iconify';
|
||||||
@ -200,14 +201,16 @@ export const loadCache: LoadIconsCache = (): void => {
|
|||||||
typeof data !== 'object' ||
|
typeof data !== 'object' ||
|
||||||
typeof data.cached !== 'number' ||
|
typeof data.cached !== 'number' ||
|
||||||
data.cached < minTime ||
|
data.cached < minTime ||
|
||||||
|
typeof data.provider !== 'string' ||
|
||||||
typeof data.data !== 'object' ||
|
typeof data.data !== 'object' ||
|
||||||
typeof data.data.prefix !== 'string'
|
typeof data.data.prefix !== 'string'
|
||||||
) {
|
) {
|
||||||
valid = false;
|
valid = false;
|
||||||
} else {
|
} else {
|
||||||
// Add icon set
|
// Add icon set
|
||||||
|
const provider = data.provider;
|
||||||
const prefix = data.data.prefix;
|
const prefix = data.data.prefix;
|
||||||
const storage = getStorage(prefix);
|
const storage = getStorage(provider, prefix);
|
||||||
valid = addIconSet(storage, data.data) as boolean;
|
valid = addIconSet(storage, data.data) as boolean;
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@ -263,7 +266,10 @@ export const loadCache: LoadIconsCache = (): void => {
|
|||||||
/**
|
/**
|
||||||
* Function to cache icons
|
* Function to cache icons
|
||||||
*/
|
*/
|
||||||
export const storeCache: CacheIcons = (data: IconifyJSON): void => {
|
export const storeCache: CacheIcons = (
|
||||||
|
provider: string,
|
||||||
|
data: IconifyJSON
|
||||||
|
): void => {
|
||||||
if (!loaded) {
|
if (!loaded) {
|
||||||
loadCache();
|
loadCache();
|
||||||
}
|
}
|
||||||
@ -292,6 +298,7 @@ export const storeCache: CacheIcons = (data: IconifyJSON): void => {
|
|||||||
try {
|
try {
|
||||||
const item: StoredItem = {
|
const item: StoredItem = {
|
||||||
cached: Math.floor(Date.now() / hour),
|
cached: Math.floor(Date.now() / hour),
|
||||||
|
provider,
|
||||||
data,
|
data,
|
||||||
};
|
};
|
||||||
func.setItem(cachePrefix + index, JSON.stringify(item));
|
func.setItem(cachePrefix + index, JSON.stringify(item));
|
||||||
|
@ -9,13 +9,14 @@ export function listToIcons(
|
|||||||
): IconifyIconName[] {
|
): IconifyIconName[] {
|
||||||
const result: IconifyIconName[] = [];
|
const result: IconifyIconName[] = [];
|
||||||
|
|
||||||
list.forEach(item => {
|
list.forEach((item) => {
|
||||||
const icon: IconifyIconName =
|
const icon: IconifyIconName =
|
||||||
typeof item === 'string'
|
typeof item === 'string'
|
||||||
? (stringToIcon(item) as IconifyIconName)
|
? (stringToIcon(item) as IconifyIconName)
|
||||||
: item;
|
: item;
|
||||||
if (!validate || validateIcon(icon)) {
|
if (!validate || validateIcon(icon)) {
|
||||||
result.push({
|
result.push({
|
||||||
|
provider: icon.provider,
|
||||||
prefix: icon.prefix,
|
prefix: icon.prefix,
|
||||||
name: icon.name,
|
name: icon.name,
|
||||||
});
|
});
|
||||||
@ -26,12 +27,12 @@ export function listToIcons(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all prefixes
|
* Get all providers
|
||||||
*/
|
*/
|
||||||
export function getPrefixes(list: IconifyIconName[]): string[] {
|
export function getProviders(list: IconifyIconName[]): string[] {
|
||||||
const prefixes: Record<string, boolean> = Object.create(null);
|
const providers: Record<string, boolean> = Object.create(null);
|
||||||
list.forEach(icon => {
|
list.forEach((icon) => {
|
||||||
prefixes[icon.prefix] = true;
|
providers[icon.provider] = true;
|
||||||
});
|
});
|
||||||
return Object.keys(prefixes);
|
return Object.keys(providers);
|
||||||
}
|
}
|
||||||
|
@ -2,10 +2,16 @@
|
|||||||
* Icon name
|
* Icon name
|
||||||
*/
|
*/
|
||||||
export interface IconifyIconName {
|
export interface IconifyIconName {
|
||||||
|
readonly provider: string;
|
||||||
readonly prefix: string;
|
readonly prefix: string;
|
||||||
readonly name: string;
|
readonly name: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Icon source: icon object without name
|
||||||
|
*/
|
||||||
|
export type IconifyIconSource = Omit<IconifyIconName, 'name'>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expression to test part of icon name.
|
* Expression to test part of icon name.
|
||||||
*/
|
*/
|
||||||
@ -15,22 +21,40 @@ const match = /^[a-z0-9]+(-[a-z0-9]+)*$/;
|
|||||||
* Convert string to Icon object.
|
* Convert string to Icon object.
|
||||||
*/
|
*/
|
||||||
export const stringToIcon = (value: string): IconifyIconName | null => {
|
export const stringToIcon = (value: string): IconifyIconName | null => {
|
||||||
// Attempt to split by colon: "prefix:name"
|
let provider = '';
|
||||||
const colonSeparated = value.split(':');
|
const colonSeparated = value.split(':');
|
||||||
if (colonSeparated.length > 2) {
|
|
||||||
|
// Check for provider with correct '@' at start
|
||||||
|
if (value.slice(0, 1) === '@') {
|
||||||
|
// First part is provider
|
||||||
|
if (colonSeparated.length < 2 || colonSeparated.length > 3) {
|
||||||
|
// "@provider:prefix:name" or "@provider:prefix-name"
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
provider = (colonSeparated.shift() as string).slice(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check split by colon: "prefix:name", "provider:prefix:name"
|
||||||
|
if (colonSeparated.length > 3 || !colonSeparated.length) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (colonSeparated.length === 2) {
|
if (colonSeparated.length > 1) {
|
||||||
|
// "prefix:name"
|
||||||
|
const name = colonSeparated.pop() as string;
|
||||||
|
const prefix = colonSeparated.pop() as string;
|
||||||
return {
|
return {
|
||||||
prefix: colonSeparated[0],
|
// Allow provider without '@': "provider:prefix:name"
|
||||||
name: colonSeparated[1],
|
provider: colonSeparated.length > 0 ? colonSeparated[0] : provider,
|
||||||
|
prefix,
|
||||||
|
name,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attempt to split by dash: "prefix-name"
|
// Attempt to split by dash: "prefix-name"
|
||||||
const dashSeparated = value.split('-');
|
const dashSeparated = colonSeparated[0].split('-');
|
||||||
if (dashSeparated.length > 1) {
|
if (dashSeparated.length > 1) {
|
||||||
return {
|
return {
|
||||||
|
provider: provider,
|
||||||
prefix: dashSeparated.shift() as string,
|
prefix: dashSeparated.shift() as string,
|
||||||
name: dashSeparated.join('-'),
|
name: dashSeparated.join('-'),
|
||||||
};
|
};
|
||||||
@ -49,5 +73,9 @@ export const validateIcon = (icon: IconifyIconName | null): boolean => {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return !!(icon.prefix.match(match) && icon.name.match(match));
|
return !!(
|
||||||
|
(icon.provider === '' || icon.provider.match(match)) &&
|
||||||
|
icon.prefix.match(match) &&
|
||||||
|
icon.name.match(match)
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
@ -19,35 +19,50 @@ export function sortIcons(icons: IconifyIconName[]): SortedIcons {
|
|||||||
missing: [],
|
missing: [],
|
||||||
pending: [],
|
pending: [],
|
||||||
};
|
};
|
||||||
const storage: Record<string, IconStorage> = Object.create(null);
|
const storage: Record<string, Record<string, IconStorage>> = Object.create(
|
||||||
|
null
|
||||||
|
);
|
||||||
|
|
||||||
// Sort icons alphabetically to prevent duplicates and make sure they are sorted in API queries
|
// Sort icons alphabetically to prevent duplicates and make sure they are sorted in API queries
|
||||||
icons.sort((a, b) => {
|
icons.sort((a, b) => {
|
||||||
if (a.prefix === b.prefix) {
|
if (a.provider !== b.provider) {
|
||||||
return a.name.localeCompare(b.name);
|
return a.provider.localeCompare(b.provider);
|
||||||
}
|
}
|
||||||
return a.prefix.localeCompare(b.prefix);
|
if (a.prefix !== b.prefix) {
|
||||||
|
return a.prefix.localeCompare(b.prefix);
|
||||||
|
}
|
||||||
|
return a.name.localeCompare(b.name);
|
||||||
});
|
});
|
||||||
|
|
||||||
let lastIcon: IconifyIconName = {
|
let lastIcon: IconifyIconName = {
|
||||||
|
provider: '',
|
||||||
prefix: '',
|
prefix: '',
|
||||||
name: '',
|
name: '',
|
||||||
};
|
};
|
||||||
icons.forEach(icon => {
|
icons.forEach((icon) => {
|
||||||
if (lastIcon.prefix === icon.prefix && lastIcon.name === icon.name) {
|
if (
|
||||||
|
lastIcon.name === icon.name &&
|
||||||
|
lastIcon.prefix === icon.prefix &&
|
||||||
|
lastIcon.provider === icon.provider
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
lastIcon = icon;
|
lastIcon = icon;
|
||||||
|
|
||||||
// Check icon
|
// Check icon
|
||||||
|
const provider = icon.provider;
|
||||||
const prefix = icon.prefix;
|
const prefix = icon.prefix;
|
||||||
const name = icon.name;
|
const name = icon.name;
|
||||||
|
|
||||||
if (storage[prefix] === void 0) {
|
if (storage[provider] === void 0) {
|
||||||
storage[prefix] = getStorage(prefix);
|
storage[provider] = Object.create(null);
|
||||||
}
|
}
|
||||||
|
const providerStorage = storage[provider];
|
||||||
|
|
||||||
const localStorage = storage[prefix];
|
if (providerStorage[prefix] === void 0) {
|
||||||
|
providerStorage[prefix] = getStorage(provider, prefix);
|
||||||
|
}
|
||||||
|
const localStorage = providerStorage[prefix];
|
||||||
|
|
||||||
let list;
|
let list;
|
||||||
if (localStorage.icons[name] !== void 0) {
|
if (localStorage.icons[name] !== void 0) {
|
||||||
@ -59,6 +74,7 @@ export function sortIcons(icons: IconifyIconName[]): SortedIcons {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const item: IconifyIconName = {
|
const item: IconifyIconName = {
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
name,
|
name,
|
||||||
};
|
};
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import { IconifyLoadIcons } from './loader';
|
import { IconifyLoadIcons } from './loader';
|
||||||
|
import { IconifyIconName } from '../icon/name';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function to check if icon is pending
|
* Function to check if icon is pending
|
||||||
*/
|
*/
|
||||||
export type IsPending = (prefix: string, name: string) => boolean;
|
export type IsPending = (icon: IconifyIconName) => boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* API interface
|
* API interface
|
||||||
|
@ -3,7 +3,7 @@ import { IconifyJSON } from '@iconify/types';
|
|||||||
/**
|
/**
|
||||||
* Function to cache loaded icons set
|
* Function to cache loaded icons set
|
||||||
*/
|
*/
|
||||||
export type CacheIcons = (data: IconifyJSON) => void;
|
export type CacheIcons = (provider: string, data: IconifyJSON) => void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function to load icons from cache
|
* Function to load icons from cache
|
||||||
|
@ -24,21 +24,25 @@ type IconRecords = Record<string, FullIconifyIcon | null>;
|
|||||||
* Storage type
|
* Storage type
|
||||||
*/
|
*/
|
||||||
export interface IconStorage {
|
export interface IconStorage {
|
||||||
|
provider: string;
|
||||||
prefix: string;
|
prefix: string;
|
||||||
icons: IconRecords;
|
icons: IconRecords;
|
||||||
missing: Record<string, number>;
|
missing: Record<string, number>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Storage by prefix
|
* Storage by provider and prefix
|
||||||
*/
|
*/
|
||||||
const storage: Record<string, IconStorage> = Object.create(null);
|
const storage: Record<string, Record<string, IconStorage>> = Object.create(
|
||||||
|
null
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create new storage
|
* Create new storage
|
||||||
*/
|
*/
|
||||||
export function newStorage(prefix: string): IconStorage {
|
export function newStorage(provider: string, prefix: string): IconStorage {
|
||||||
return {
|
return {
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
icons: Object.create(null),
|
icons: Object.create(null),
|
||||||
missing: Object.create(null),
|
missing: Object.create(null),
|
||||||
@ -46,20 +50,31 @@ export function newStorage(prefix: string): IconStorage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get storage for prefix
|
* Get storage for provider and prefix
|
||||||
*/
|
*/
|
||||||
export function getStorage(prefix: string): IconStorage {
|
export function getStorage(provider: string, prefix: string): IconStorage {
|
||||||
if (storage[prefix] === void 0) {
|
if (storage[provider] === void 0) {
|
||||||
storage[prefix] = newStorage(prefix);
|
storage[provider] = Object.create(null);
|
||||||
}
|
}
|
||||||
return storage[prefix];
|
const providerStorage = storage[provider];
|
||||||
|
if (providerStorage[prefix] === void 0) {
|
||||||
|
providerStorage[prefix] = newStorage(provider, prefix);
|
||||||
|
}
|
||||||
|
return providerStorage[prefix];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all providers
|
||||||
|
*/
|
||||||
|
export function listStoredProviders(): string[] {
|
||||||
|
return Object.keys(storage);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all prefixes
|
* Get all prefixes
|
||||||
*/
|
*/
|
||||||
export function listStoredPrefixes(): string[] {
|
export function listStoredPrefixes(provider: string): string[] {
|
||||||
return Object.keys(storage);
|
return storage[provider] === void 0 ? [] : Object.keys(storage[provider]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -119,7 +134,7 @@ export function addIconSet(
|
|||||||
// Check for missing icons list returned by API
|
// Check for missing icons list returned by API
|
||||||
if (data.not_found instanceof Array) {
|
if (data.not_found instanceof Array) {
|
||||||
const t = Date.now();
|
const t = Date.now();
|
||||||
data.not_found.forEach(name => {
|
data.not_found.forEach((name) => {
|
||||||
storage.missing[name] = t;
|
storage.missing[name] = t;
|
||||||
if (list === 'all') {
|
if (list === 'all') {
|
||||||
added.push(name);
|
added.push(name);
|
||||||
@ -134,7 +149,7 @@ export function addIconSet(
|
|||||||
|
|
||||||
// Get default values
|
// Get default values
|
||||||
const defaults = Object.create(null);
|
const defaults = Object.create(null);
|
||||||
defaultsKeys.forEach(key => {
|
defaultsKeys.forEach((key) => {
|
||||||
if (data[key] !== void 0 && typeof data[key] !== 'object') {
|
if (data[key] !== void 0 && typeof data[key] !== 'object') {
|
||||||
defaults[key] = data[key];
|
defaults[key] = data[key];
|
||||||
}
|
}
|
||||||
@ -142,7 +157,7 @@ export function addIconSet(
|
|||||||
|
|
||||||
// Get icons
|
// Get icons
|
||||||
const icons = data.icons;
|
const icons = data.icons;
|
||||||
Object.keys(icons).forEach(name => {
|
Object.keys(icons).forEach((name) => {
|
||||||
const icon = icons[name];
|
const icon = icons[name];
|
||||||
if (typeof icon.body !== 'string') {
|
if (typeof icon.body !== 'string') {
|
||||||
throw new Error('Invalid icon');
|
throw new Error('Invalid icon');
|
||||||
@ -160,7 +175,7 @@ export function addIconSet(
|
|||||||
// Get aliases
|
// Get aliases
|
||||||
if (typeof data.aliases === 'object') {
|
if (typeof data.aliases === 'object') {
|
||||||
const aliases = data.aliases;
|
const aliases = data.aliases;
|
||||||
Object.keys(aliases).forEach(name => {
|
Object.keys(aliases).forEach((name) => {
|
||||||
const icon = resolveAlias(aliases[name], icons, aliases, 1);
|
const icon = resolveAlias(aliases[name], icons, aliases, 1);
|
||||||
if (icon) {
|
if (icon) {
|
||||||
// Freeze icon to make sure it will not be modified
|
// Freeze icon to make sure it will not be modified
|
||||||
|
@ -7,12 +7,13 @@ import {
|
|||||||
} from '../../lib/icon/name';
|
} from '../../lib/icon/name';
|
||||||
|
|
||||||
describe('Testing icon name', () => {
|
describe('Testing icon name', () => {
|
||||||
it('Converting and validating', () => {
|
it('Simple icon names', () => {
|
||||||
let icon;
|
let icon;
|
||||||
|
|
||||||
// Simple prefix-name
|
// Simple prefix-name
|
||||||
icon = stringToIcon('fa-home') as IconifyIconName;
|
icon = stringToIcon('fa-home') as IconifyIconName;
|
||||||
expect(icon).to.be.eql({
|
expect(icon).to.be.eql({
|
||||||
|
provider: '',
|
||||||
prefix: 'fa',
|
prefix: 'fa',
|
||||||
name: 'home',
|
name: 'home',
|
||||||
});
|
});
|
||||||
@ -21,6 +22,7 @@ describe('Testing icon name', () => {
|
|||||||
// Simple prefix:name
|
// Simple prefix:name
|
||||||
icon = stringToIcon('fa:arrow-left') as IconifyIconName;
|
icon = stringToIcon('fa:arrow-left') as IconifyIconName;
|
||||||
expect(icon).to.be.eql({
|
expect(icon).to.be.eql({
|
||||||
|
provider: '',
|
||||||
prefix: 'fa',
|
prefix: 'fa',
|
||||||
name: 'arrow-left',
|
name: 'arrow-left',
|
||||||
});
|
});
|
||||||
@ -29,11 +31,17 @@ describe('Testing icon name', () => {
|
|||||||
// Longer prefix:name
|
// Longer prefix:name
|
||||||
icon = stringToIcon('mdi-light:home-outline') as IconifyIconName;
|
icon = stringToIcon('mdi-light:home-outline') as IconifyIconName;
|
||||||
expect(icon).to.be.eql({
|
expect(icon).to.be.eql({
|
||||||
|
provider: '',
|
||||||
prefix: 'mdi-light',
|
prefix: 'mdi-light',
|
||||||
name: 'home-outline',
|
name: 'home-outline',
|
||||||
});
|
});
|
||||||
expect(validateIcon(icon)).to.be.equal(true);
|
expect(validateIcon(icon)).to.be.equal(true);
|
||||||
|
|
||||||
|
// Missing icon name
|
||||||
|
icon = stringToIcon('@iconify-home-icon');
|
||||||
|
expect(icon).to.be.eql(null);
|
||||||
|
expect(validateIcon(icon)).to.be.equal(false);
|
||||||
|
|
||||||
// Underscore is not an acceptable separator
|
// Underscore is not an acceptable separator
|
||||||
icon = stringToIcon('fa_home');
|
icon = stringToIcon('fa_home');
|
||||||
expect(icon).to.be.eql(null);
|
expect(icon).to.be.eql(null);
|
||||||
@ -42,19 +50,21 @@ describe('Testing icon name', () => {
|
|||||||
// Invalid character '_': fail validateIcon
|
// Invalid character '_': fail validateIcon
|
||||||
icon = stringToIcon('fa:home_outline') as IconifyIconName;
|
icon = stringToIcon('fa:home_outline') as IconifyIconName;
|
||||||
expect(icon).to.be.eql({
|
expect(icon).to.be.eql({
|
||||||
|
provider: '',
|
||||||
prefix: 'fa',
|
prefix: 'fa',
|
||||||
name: 'home_outline',
|
name: 'home_outline',
|
||||||
});
|
});
|
||||||
expect(validateIcon(icon)).to.be.equal(false);
|
expect(validateIcon(icon)).to.be.equal(false);
|
||||||
|
|
||||||
// Too many colons: fail stringToIcon
|
// Too many colons: fail stringToIcon
|
||||||
icon = stringToIcon('mdi-light:home:outline');
|
icon = stringToIcon('mdi:light:home:outline');
|
||||||
expect(icon).to.be.eql(null);
|
expect(icon).to.be.eql(null);
|
||||||
expect(validateIcon(icon)).to.be.equal(false);
|
expect(validateIcon(icon)).to.be.equal(false);
|
||||||
|
|
||||||
// Upper case: fail validateIcon
|
// Upper case: fail validateIcon
|
||||||
icon = stringToIcon('MD:Home') as IconifyIconName;
|
icon = stringToIcon('MD:Home') as IconifyIconName;
|
||||||
expect(icon).to.be.eql({
|
expect(icon).to.be.eql({
|
||||||
|
provider: '',
|
||||||
prefix: 'MD',
|
prefix: 'MD',
|
||||||
name: 'Home',
|
name: 'Home',
|
||||||
});
|
});
|
||||||
@ -63,6 +73,7 @@ describe('Testing icon name', () => {
|
|||||||
// Numbers: pass
|
// Numbers: pass
|
||||||
icon = stringToIcon('1:foo') as IconifyIconName;
|
icon = stringToIcon('1:foo') as IconifyIconName;
|
||||||
expect(icon).to.be.eql({
|
expect(icon).to.be.eql({
|
||||||
|
provider: '',
|
||||||
prefix: '1',
|
prefix: '1',
|
||||||
name: 'foo',
|
name: 'foo',
|
||||||
});
|
});
|
||||||
@ -71,9 +82,68 @@ describe('Testing icon name', () => {
|
|||||||
// Accented letters: fail validateIcon
|
// Accented letters: fail validateIcon
|
||||||
icon = stringToIcon('md-fõö') as IconifyIconName;
|
icon = stringToIcon('md-fõö') as IconifyIconName;
|
||||||
expect(icon).to.be.eql({
|
expect(icon).to.be.eql({
|
||||||
|
provider: '',
|
||||||
prefix: 'md',
|
prefix: 'md',
|
||||||
name: 'fõö',
|
name: 'fõö',
|
||||||
});
|
});
|
||||||
expect(validateIcon(icon)).to.be.equal(false);
|
expect(validateIcon(icon)).to.be.equal(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Providers', () => {
|
||||||
|
let icon;
|
||||||
|
|
||||||
|
// Simple @provider:prefix-name
|
||||||
|
icon = stringToIcon('@iconify:fa-home') as IconifyIconName;
|
||||||
|
expect(icon).to.be.eql({
|
||||||
|
provider: 'iconify',
|
||||||
|
prefix: 'fa',
|
||||||
|
name: 'home',
|
||||||
|
});
|
||||||
|
expect(validateIcon(icon)).to.be.equal(true);
|
||||||
|
|
||||||
|
// Simple @provider:prefix:name
|
||||||
|
icon = stringToIcon('@iconify:fa:arrow-left') as IconifyIconName;
|
||||||
|
expect(icon).to.be.eql({
|
||||||
|
provider: 'iconify',
|
||||||
|
prefix: 'fa',
|
||||||
|
name: 'arrow-left',
|
||||||
|
});
|
||||||
|
expect(validateIcon(icon)).to.be.equal(true);
|
||||||
|
|
||||||
|
// Longer @provider:prefix:name
|
||||||
|
icon = stringToIcon(
|
||||||
|
'@iconify-backup:mdi-light:home-outline'
|
||||||
|
) as IconifyIconName;
|
||||||
|
expect(icon).to.be.eql({
|
||||||
|
provider: 'iconify-backup',
|
||||||
|
prefix: 'mdi-light',
|
||||||
|
name: 'home-outline',
|
||||||
|
});
|
||||||
|
expect(validateIcon(icon)).to.be.equal(true);
|
||||||
|
|
||||||
|
// Missing @ for provider
|
||||||
|
icon = stringToIcon(
|
||||||
|
'iconify-backup:mdi-light:home-outline'
|
||||||
|
) as IconifyIconName;
|
||||||
|
expect(icon).to.be.eql({
|
||||||
|
provider: 'iconify-backup',
|
||||||
|
prefix: 'mdi-light',
|
||||||
|
name: 'home-outline',
|
||||||
|
});
|
||||||
|
expect(validateIcon(icon)).to.be.equal(true);
|
||||||
|
|
||||||
|
// Too many colons: fail stringToIcon
|
||||||
|
icon = stringToIcon('@mdi:light:home:outline');
|
||||||
|
expect(icon).to.be.eql(null);
|
||||||
|
expect(validateIcon(icon)).to.be.equal(false);
|
||||||
|
|
||||||
|
// Upper case: fail validateIcon
|
||||||
|
icon = stringToIcon('@MD:home-outline') as IconifyIconName;
|
||||||
|
expect(icon).to.be.eql({
|
||||||
|
provider: 'MD',
|
||||||
|
prefix: 'home',
|
||||||
|
name: 'outline',
|
||||||
|
});
|
||||||
|
expect(validateIcon(icon)).to.be.equal(false);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -13,7 +13,7 @@ import { IconifyJSON } from '@iconify/types';
|
|||||||
|
|
||||||
describe('Testing storage', () => {
|
describe('Testing storage', () => {
|
||||||
it('Adding icon', () => {
|
it('Adding icon', () => {
|
||||||
const storage = newStorage('foo');
|
const storage = newStorage('', 'foo');
|
||||||
|
|
||||||
// Add one icon
|
// Add one icon
|
||||||
addIcon(storage, 'test', {
|
addIcon(storage, 'test', {
|
||||||
@ -82,7 +82,7 @@ describe('Testing storage', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Adding simple icon set', () => {
|
it('Adding simple icon set', () => {
|
||||||
const storage = newStorage('foo');
|
const storage = newStorage('', 'foo');
|
||||||
|
|
||||||
// Add two icons
|
// Add two icons
|
||||||
expect(
|
expect(
|
||||||
@ -138,7 +138,7 @@ describe('Testing storage', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Icon set with invalid default values', () => {
|
it('Icon set with invalid default values', () => {
|
||||||
const storage = newStorage('foo');
|
const storage = newStorage('', 'foo');
|
||||||
|
|
||||||
// Missing prefix, invalid default values
|
// Missing prefix, invalid default values
|
||||||
expect(
|
expect(
|
||||||
@ -205,7 +205,7 @@ describe('Testing storage', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Icon set with simple aliases', () => {
|
it('Icon set with simple aliases', () => {
|
||||||
const storage = newStorage('foo');
|
const storage = newStorage('', 'foo');
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
addIconSet(storage, {
|
addIconSet(storage, {
|
||||||
@ -275,7 +275,7 @@ describe('Testing storage', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Icon set with nested aliases', () => {
|
it('Icon set with nested aliases', () => {
|
||||||
const storage = newStorage('foo');
|
const storage = newStorage('', 'foo');
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
addIconSet(storage, {
|
addIconSet(storage, {
|
||||||
@ -402,7 +402,7 @@ describe('Testing storage', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Icon set with aliases that use transformations', () => {
|
it('Icon set with aliases that use transformations', () => {
|
||||||
const storage = newStorage('arty-animated');
|
const storage = newStorage('iconify', 'arty-animated');
|
||||||
const iconBody =
|
const iconBody =
|
||||||
'<g stroke="currentColor" stroke-width="16" stroke-linecap="round" stroke-linejoin="round" fill="none" fill-rule="evenodd"><path d="M40 64l48-48" class="animation-delay-0 animation-duration-10 animate-stroke stroke-length-102"/><path d="M40 64l48 48" class="animation-delay-0 animation-duration-10 animate-stroke stroke-length-102"/></g>';
|
'<g stroke="currentColor" stroke-width="16" stroke-linecap="round" stroke-linejoin="round" fill="none" fill-rule="evenodd"><path d="M40 64l48-48" class="animation-delay-0 animation-duration-10 animate-stroke stroke-length-102"/><path d="M40 64l48 48" class="animation-delay-0 animation-duration-10 animate-stroke stroke-length-102"/></g>';
|
||||||
|
|
||||||
|
@ -18,11 +18,12 @@ describe('Testing API callbacks', () => {
|
|||||||
return 'api-cb-test-' + (prefixCounter < 10 ? '0' : '') + prefixCounter;
|
return 'api-cb-test-' + (prefixCounter < 10 ? '0' : '') + prefixCounter;
|
||||||
}
|
}
|
||||||
|
|
||||||
it('Simple callback', done => {
|
it('Simple callback', (done) => {
|
||||||
|
const provider = 'iconify';
|
||||||
const prefix = nextPrefix();
|
const prefix = nextPrefix();
|
||||||
let counter = 0;
|
let counter = 0;
|
||||||
|
|
||||||
const storage = getStorage(prefix);
|
const storage = getStorage(provider, prefix);
|
||||||
const abort = storeCallback(
|
const abort = storeCallback(
|
||||||
(loaded, missing, pending, unsubscribe) => {
|
(loaded, missing, pending, unsubscribe) => {
|
||||||
expect(unsubscribe).to.be.equal(abort);
|
expect(unsubscribe).to.be.equal(abort);
|
||||||
@ -33,23 +34,28 @@ describe('Testing API callbacks', () => {
|
|||||||
// First run - icon1 should be loaded, icon3 should be missing
|
// First run - icon1 should be loaded, icon3 should be missing
|
||||||
expect(loaded).to.be.eql([
|
expect(loaded).to.be.eql([
|
||||||
{
|
{
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
name: 'icon1',
|
name: 'icon1',
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
expect(missing).to.be.eql([
|
expect(missing).to.be.eql([
|
||||||
{
|
{
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
name: 'icon3',
|
name: 'icon3',
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
expect(pending).to.be.eql([
|
expect(pending).to.be.eql([
|
||||||
{
|
{
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
name: 'icon2',
|
name: 'icon2',
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
expect(callbacks[prefix].length).to.be.equal(1);
|
expect(callbacks[provider][prefix].length).to.be.equal(
|
||||||
|
1
|
||||||
|
);
|
||||||
|
|
||||||
// Add icon2 and trigger update
|
// Add icon2 and trigger update
|
||||||
addIconSet(storage, {
|
addIconSet(storage, {
|
||||||
@ -61,54 +67,67 @@ describe('Testing API callbacks', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
updateCallbacks(prefix);
|
updateCallbacks(provider, prefix);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
// Second run - icon2 should be added, completing callback
|
// Second run - icon2 should be added, completing callback
|
||||||
expect(loaded).to.be.eql([
|
expect(loaded).to.be.eql([
|
||||||
{
|
{
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
name: 'icon1',
|
name: 'icon1',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
name: 'icon2',
|
name: 'icon2',
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
expect(missing).to.be.eql([
|
expect(missing).to.be.eql([
|
||||||
{
|
{
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
name: 'icon3',
|
name: 'icon3',
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
expect(pending).to.be.eql([]);
|
expect(pending).to.be.eql([]);
|
||||||
expect(callbacks[prefix].length).to.be.equal(0);
|
expect(callbacks[provider][prefix].length).to.be.equal(
|
||||||
|
0
|
||||||
|
);
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
sortIcons([
|
sortIcons([
|
||||||
{
|
{
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
name: 'icon1',
|
name: 'icon1',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
name: 'icon2',
|
name: 'icon2',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
name: 'icon3',
|
name: 'icon3',
|
||||||
},
|
},
|
||||||
]),
|
]),
|
||||||
[prefix]
|
[
|
||||||
|
{
|
||||||
|
provider,
|
||||||
|
prefix,
|
||||||
|
},
|
||||||
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
// Test callbacks
|
// Test callbacks
|
||||||
expect(callbacks[prefix].length).to.be.equal(1);
|
expect(callbacks[provider][prefix].length).to.be.equal(1);
|
||||||
|
|
||||||
// Test update - should do nothing
|
// Test update - should do nothing
|
||||||
updateCallbacks(prefix);
|
updateCallbacks(provider, prefix);
|
||||||
|
|
||||||
// Wait for tick because updateCallbacks will use one
|
// Wait for tick because updateCallbacks will use one
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@ -125,14 +144,15 @@ describe('Testing API callbacks', () => {
|
|||||||
},
|
},
|
||||||
not_found: ['icon3'],
|
not_found: ['icon3'],
|
||||||
});
|
});
|
||||||
updateCallbacks(prefix);
|
updateCallbacks(provider, prefix);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Callback that should not be stored', () => {
|
it('Callback that should not be stored', () => {
|
||||||
|
const provider = '';
|
||||||
const prefix = nextPrefix();
|
const prefix = nextPrefix();
|
||||||
|
|
||||||
const storage = getStorage(prefix);
|
const storage = getStorage(provider, prefix);
|
||||||
addIconSet(storage, {
|
addIconSet(storage, {
|
||||||
prefix,
|
prefix,
|
||||||
icons: {
|
icons: {
|
||||||
@ -152,30 +172,39 @@ describe('Testing API callbacks', () => {
|
|||||||
},
|
},
|
||||||
sortIcons([
|
sortIcons([
|
||||||
{
|
{
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
name: 'icon1',
|
name: 'icon1',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
name: 'icon2',
|
name: 'icon2',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
name: 'icon3',
|
name: 'icon3',
|
||||||
},
|
},
|
||||||
]),
|
]),
|
||||||
[prefix]
|
[
|
||||||
|
{
|
||||||
|
provider,
|
||||||
|
prefix,
|
||||||
|
},
|
||||||
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
// callbacks should not have been initialised
|
// callbacks should not have been initialised
|
||||||
expect(callbacks[prefix]).to.be.equal(void 0);
|
expect(callbacks[prefix]).to.be.equal(void 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Cancel callback', done => {
|
it('Cancel callback', (done) => {
|
||||||
|
const provider = 'foo';
|
||||||
const prefix = nextPrefix();
|
const prefix = nextPrefix();
|
||||||
let counter = 0;
|
let counter = 0;
|
||||||
|
|
||||||
const storage = getStorage(prefix);
|
const storage = getStorage(provider, prefix);
|
||||||
const abort = storeCallback(
|
const abort = storeCallback(
|
||||||
(loaded, missing, pending, unsubscribe) => {
|
(loaded, missing, pending, unsubscribe) => {
|
||||||
expect(unsubscribe).to.be.equal(abort);
|
expect(unsubscribe).to.be.equal(abort);
|
||||||
@ -186,23 +215,26 @@ describe('Testing API callbacks', () => {
|
|||||||
// First run - icon1 should be loaded, icon3 should be missing
|
// First run - icon1 should be loaded, icon3 should be missing
|
||||||
expect(loaded).to.be.eql([
|
expect(loaded).to.be.eql([
|
||||||
{
|
{
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
name: 'icon1',
|
name: 'icon1',
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
expect(missing).to.be.eql([
|
expect(missing).to.be.eql([
|
||||||
{
|
{
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
name: 'icon3',
|
name: 'icon3',
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
expect(pending).to.be.eql([
|
expect(pending).to.be.eql([
|
||||||
{
|
{
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
name: 'icon2',
|
name: 'icon2',
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
expect(callbacks[prefix].length).to.be.equal(1);
|
expect(callbacks[provider][prefix].length).to.be.equal(1);
|
||||||
|
|
||||||
// Add icon2 and trigger update
|
// Add icon2 and trigger update
|
||||||
addIconSet(storage, {
|
addIconSet(storage, {
|
||||||
@ -214,35 +246,43 @@ describe('Testing API callbacks', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
updateCallbacks(prefix);
|
updateCallbacks(provider, prefix);
|
||||||
|
|
||||||
// Unsubscribe and set timer to call done()
|
// Unsubscribe and set timer to call done()
|
||||||
unsubscribe();
|
unsubscribe();
|
||||||
expect(callbacks[prefix].length).to.be.equal(0);
|
expect(callbacks[provider][prefix].length).to.be.equal(0);
|
||||||
setTimeout(done);
|
setTimeout(done);
|
||||||
},
|
},
|
||||||
sortIcons([
|
sortIcons([
|
||||||
{
|
{
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
name: 'icon1',
|
name: 'icon1',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
name: 'icon2',
|
name: 'icon2',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
name: 'icon3',
|
name: 'icon3',
|
||||||
},
|
},
|
||||||
]),
|
]),
|
||||||
[prefix]
|
[
|
||||||
|
{
|
||||||
|
provider,
|
||||||
|
prefix,
|
||||||
|
},
|
||||||
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
// Test callbacks
|
// Test callbacks
|
||||||
expect(callbacks[prefix].length).to.be.equal(1);
|
expect(callbacks[provider][prefix].length).to.be.equal(1);
|
||||||
|
|
||||||
// Test update - should do nothing
|
// Test update - should do nothing
|
||||||
updateCallbacks(prefix);
|
updateCallbacks(provider, prefix);
|
||||||
|
|
||||||
// Wait for tick because updateCallbacks will use one
|
// Wait for tick because updateCallbacks will use one
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@ -259,17 +299,18 @@ describe('Testing API callbacks', () => {
|
|||||||
},
|
},
|
||||||
not_found: ['icon3'],
|
not_found: ['icon3'],
|
||||||
});
|
});
|
||||||
updateCallbacks(prefix);
|
updateCallbacks(provider, prefix);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Multiple prefixes', done => {
|
it('Multiple prefixes', (done) => {
|
||||||
|
const provider = '';
|
||||||
const prefix1 = nextPrefix();
|
const prefix1 = nextPrefix();
|
||||||
const prefix2 = nextPrefix();
|
const prefix2 = nextPrefix();
|
||||||
let counter = 0;
|
let counter = 0;
|
||||||
|
|
||||||
const storage1 = getStorage(prefix1);
|
const storage1 = getStorage(provider, prefix1);
|
||||||
const storage2 = getStorage(prefix2);
|
const storage2 = getStorage(provider, prefix2);
|
||||||
|
|
||||||
const abort = storeCallback(
|
const abort = storeCallback(
|
||||||
(loaded, missing, pending, unsubscribe) => {
|
(loaded, missing, pending, unsubscribe) => {
|
||||||
@ -281,24 +322,31 @@ describe('Testing API callbacks', () => {
|
|||||||
// First run - icon1 should be loaded, icon3 should be missing
|
// First run - icon1 should be loaded, icon3 should be missing
|
||||||
expect(loaded).to.be.eql([
|
expect(loaded).to.be.eql([
|
||||||
{
|
{
|
||||||
|
provider,
|
||||||
prefix: prefix1,
|
prefix: prefix1,
|
||||||
name: 'icon1',
|
name: 'icon1',
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
expect(missing).to.be.eql([
|
expect(missing).to.be.eql([
|
||||||
{
|
{
|
||||||
|
provider,
|
||||||
prefix: prefix1,
|
prefix: prefix1,
|
||||||
name: 'icon3',
|
name: 'icon3',
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
expect(pending).to.be.eql([
|
expect(pending).to.be.eql([
|
||||||
{
|
{
|
||||||
|
provider,
|
||||||
prefix: prefix2,
|
prefix: prefix2,
|
||||||
name: 'icon2',
|
name: 'icon2',
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
expect(callbacks[prefix1].length).to.be.equal(0);
|
expect(callbacks[provider][prefix1].length).to.be.equal(
|
||||||
expect(callbacks[prefix2].length).to.be.equal(1);
|
0
|
||||||
|
);
|
||||||
|
expect(callbacks[provider][prefix2].length).to.be.equal(
|
||||||
|
1
|
||||||
|
);
|
||||||
|
|
||||||
// Add icon2 and trigger update
|
// Add icon2 and trigger update
|
||||||
addIconSet(storage2, {
|
addIconSet(storage2, {
|
||||||
@ -310,13 +358,17 @@ describe('Testing API callbacks', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
updateCallbacks(prefix2);
|
updateCallbacks(provider, prefix2);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
// Second run - icon2 should be loaded
|
// Second run - icon2 should be loaded
|
||||||
expect(callbacks[prefix1].length).to.be.equal(0);
|
expect(callbacks[provider][prefix1].length).to.be.equal(
|
||||||
expect(callbacks[prefix2].length).to.be.equal(0);
|
0
|
||||||
|
);
|
||||||
|
expect(callbacks[provider][prefix2].length).to.be.equal(
|
||||||
|
0
|
||||||
|
);
|
||||||
done();
|
done();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -326,27 +378,33 @@ describe('Testing API callbacks', () => {
|
|||||||
},
|
},
|
||||||
sortIcons([
|
sortIcons([
|
||||||
{
|
{
|
||||||
|
provider,
|
||||||
prefix: prefix1,
|
prefix: prefix1,
|
||||||
name: 'icon1',
|
name: 'icon1',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
provider,
|
||||||
prefix: prefix2,
|
prefix: prefix2,
|
||||||
name: 'icon2',
|
name: 'icon2',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
provider,
|
||||||
prefix: prefix1,
|
prefix: prefix1,
|
||||||
name: 'icon3',
|
name: 'icon3',
|
||||||
},
|
},
|
||||||
]),
|
]),
|
||||||
[prefix1, prefix2]
|
[
|
||||||
|
{ provider, prefix: prefix1 },
|
||||||
|
{ provider, prefix: prefix2 },
|
||||||
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
// Test callbacks
|
// Test callbacks
|
||||||
expect(callbacks[prefix1].length).to.be.equal(1);
|
expect(callbacks[provider][prefix1].length).to.be.equal(1);
|
||||||
expect(callbacks[prefix2].length).to.be.equal(1);
|
expect(callbacks[provider][prefix2].length).to.be.equal(1);
|
||||||
|
|
||||||
// Test update - should do nothing
|
// Test update - should do nothing
|
||||||
updateCallbacks(prefix1);
|
updateCallbacks(provider, prefix1);
|
||||||
|
|
||||||
// Wait for tick because updateCallbacks will use one
|
// Wait for tick because updateCallbacks will use one
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@ -363,7 +421,150 @@ describe('Testing API callbacks', () => {
|
|||||||
},
|
},
|
||||||
not_found: ['icon3'],
|
not_found: ['icon3'],
|
||||||
});
|
});
|
||||||
updateCallbacks(prefix1);
|
updateCallbacks(provider, prefix1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Multiple providers', (done) => {
|
||||||
|
const provider1 = nextPrefix();
|
||||||
|
const provider2 = nextPrefix();
|
||||||
|
const prefix1 = nextPrefix();
|
||||||
|
const prefix2 = nextPrefix();
|
||||||
|
let counter = 0;
|
||||||
|
|
||||||
|
const storage1 = getStorage(provider1, prefix1);
|
||||||
|
const storage2 = getStorage(provider2, prefix2);
|
||||||
|
|
||||||
|
const abort = storeCallback(
|
||||||
|
(loaded, missing, pending, unsubscribe) => {
|
||||||
|
expect(unsubscribe).to.be.equal(abort);
|
||||||
|
|
||||||
|
counter++;
|
||||||
|
switch (counter) {
|
||||||
|
case 1:
|
||||||
|
// First run - icon1 should be loaded, icon3 should be missing
|
||||||
|
expect(loaded).to.be.eql([
|
||||||
|
{
|
||||||
|
provider: provider1,
|
||||||
|
prefix: prefix1,
|
||||||
|
name: 'icon1',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
expect(missing).to.be.eql([
|
||||||
|
{
|
||||||
|
provider: provider1,
|
||||||
|
prefix: prefix1,
|
||||||
|
name: 'icon3',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
expect(pending).to.be.eql([
|
||||||
|
{
|
||||||
|
provider: provider2,
|
||||||
|
prefix: prefix2,
|
||||||
|
name: 'icon2',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
expect(
|
||||||
|
callbacks[provider1][prefix1].length
|
||||||
|
).to.be.equal(0);
|
||||||
|
expect(
|
||||||
|
callbacks[provider2][prefix2].length
|
||||||
|
).to.be.equal(1);
|
||||||
|
|
||||||
|
// Make sure providers/prefixes aren't mixed
|
||||||
|
expect(callbacks[provider1][prefix2]).to.be.equal(
|
||||||
|
void 0
|
||||||
|
);
|
||||||
|
expect(callbacks[provider2][prefix1]).to.be.equal(
|
||||||
|
void 0
|
||||||
|
);
|
||||||
|
|
||||||
|
// Add icon2 and trigger update
|
||||||
|
addIconSet(storage2, {
|
||||||
|
prefix: prefix2,
|
||||||
|
icons: {
|
||||||
|
icon2: {
|
||||||
|
body: '<g></g>',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
updateCallbacks(provider2, prefix2);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
// Second run - icon2 should be loaded
|
||||||
|
expect(
|
||||||
|
callbacks[provider1][prefix1].length
|
||||||
|
).to.be.equal(0);
|
||||||
|
expect(
|
||||||
|
callbacks[provider2][prefix2].length
|
||||||
|
).to.be.equal(0);
|
||||||
|
|
||||||
|
// Make sure providers/prefixes aren't mixed
|
||||||
|
expect(callbacks[provider1][prefix2]).to.be.equal(
|
||||||
|
void 0
|
||||||
|
);
|
||||||
|
expect(callbacks[provider2][prefix1]).to.be.equal(
|
||||||
|
void 0
|
||||||
|
);
|
||||||
|
|
||||||
|
done();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
done('Callback was called ' + counter + ' times.');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
sortIcons([
|
||||||
|
{
|
||||||
|
provider: provider1,
|
||||||
|
prefix: prefix1,
|
||||||
|
name: 'icon1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provider: provider2,
|
||||||
|
prefix: prefix2,
|
||||||
|
name: 'icon2',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provider: provider1,
|
||||||
|
prefix: prefix1,
|
||||||
|
name: 'icon3',
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
[
|
||||||
|
{ provider: provider1, prefix: prefix1 },
|
||||||
|
{ provider: provider2, prefix: prefix2 },
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
// Test callbacks
|
||||||
|
expect(callbacks[provider1][prefix1].length).to.be.equal(1);
|
||||||
|
expect(callbacks[provider2][prefix2].length).to.be.equal(1);
|
||||||
|
|
||||||
|
expect(callbacks[provider1][prefix2]).to.be.equal(void 0);
|
||||||
|
expect(callbacks[provider2][prefix1]).to.be.equal(void 0);
|
||||||
|
|
||||||
|
// Test update - should do nothing
|
||||||
|
updateCallbacks(provider1, prefix1);
|
||||||
|
|
||||||
|
// Wait for tick because updateCallbacks will use one
|
||||||
|
setTimeout(() => {
|
||||||
|
// Callback should not have been called yet
|
||||||
|
expect(counter).to.be.equal(0);
|
||||||
|
|
||||||
|
// Add few icons and run updateCallbacks
|
||||||
|
addIconSet(storage1, {
|
||||||
|
prefix: prefix1,
|
||||||
|
icons: {
|
||||||
|
icon1: {
|
||||||
|
body: '<g></g>',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
not_found: ['icon3'],
|
||||||
|
});
|
||||||
|
updateCallbacks(provider1, prefix1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -9,7 +9,7 @@ import {
|
|||||||
IconifyAPIConfig,
|
IconifyAPIConfig,
|
||||||
} from '../../lib/api/config';
|
} from '../../lib/api/config';
|
||||||
import {
|
import {
|
||||||
setAPIModule,
|
setProviderAPIModule,
|
||||||
APIQueryParams,
|
APIQueryParams,
|
||||||
getAPIModule,
|
getAPIModule,
|
||||||
IconifyAPIModule,
|
IconifyAPIModule,
|
||||||
@ -25,10 +25,12 @@ describe('Testing API modules', () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const prepareQuery = (
|
const prepareQuery = (
|
||||||
|
provider: string,
|
||||||
prefix: string,
|
prefix: string,
|
||||||
icons: string[]
|
icons: string[]
|
||||||
): APIQueryParams[] => {
|
): APIQueryParams[] => {
|
||||||
const item: APIQueryParams = {
|
const item: APIQueryParams = {
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
icons,
|
icons,
|
||||||
};
|
};
|
||||||
@ -44,42 +46,36 @@ describe('Testing API modules', () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
it('Empty module', () => {
|
it('Empty module', () => {
|
||||||
const prefix = nextPrefix();
|
const provider = nextPrefix();
|
||||||
|
|
||||||
// Set config
|
// Set config
|
||||||
setAPIConfig(
|
setAPIConfig(provider, {
|
||||||
{
|
resources: ['https://localhost:3000'],
|
||||||
resources: ['https://localhost:3000'],
|
maxURL: 500,
|
||||||
maxURL: 500,
|
});
|
||||||
},
|
|
||||||
prefix
|
|
||||||
);
|
|
||||||
|
|
||||||
// Set fake module
|
// Set fake module
|
||||||
setAPIModule(
|
setProviderAPIModule(provider, {
|
||||||
{
|
prepare: prepareQuery,
|
||||||
prepare: prepareQuery,
|
send: sendQuery,
|
||||||
send: sendQuery,
|
});
|
||||||
},
|
|
||||||
prefix
|
|
||||||
);
|
|
||||||
|
|
||||||
// Get config
|
// Get config
|
||||||
const config = getAPIConfig(prefix) as IconifyAPIConfig;
|
const config = getAPIConfig(provider) as IconifyAPIConfig;
|
||||||
expect(config).to.not.be.equal(null);
|
expect(config).to.not.be.equal(void 0);
|
||||||
|
|
||||||
// Check setAPIConfig
|
// Check setAPIConfig
|
||||||
expect(config.resources).to.be.eql(['https://localhost:3000']);
|
expect(config.resources).to.be.eql(['https://localhost:3000']);
|
||||||
|
|
||||||
// Check getAPIModule()
|
// Check getAPIModule()
|
||||||
const item = getAPIModule(prefix) as IconifyAPIModule;
|
const item = getAPIModule(provider) as IconifyAPIModule;
|
||||||
expect(item).to.not.be.equal(null);
|
expect(item).to.not.be.equal(void 0);
|
||||||
expect(item.prepare).to.be.equal(prepareQuery);
|
expect(item.prepare).to.be.equal(prepareQuery);
|
||||||
expect(item.send).to.be.equal(sendQuery);
|
expect(item.send).to.be.equal(sendQuery);
|
||||||
|
|
||||||
// Get module for different prefix to make sure it is empty
|
// Get module for different provider to make sure it is empty
|
||||||
const prefix2 = nextPrefix();
|
const provider2 = nextPrefix();
|
||||||
const item2 = getAPIModule(prefix2);
|
const item2 = getAPIModule(provider2);
|
||||||
expect(item2).to.be.equal(null);
|
expect(item2).to.be.equal(void 0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
import 'mocha';
|
import 'mocha';
|
||||||
import { expect } from 'chai';
|
import { expect } from 'chai';
|
||||||
import { RedundancyPendingItem } from '@cyberalien/redundancy';
|
import { RedundancyPendingItem } from '@cyberalien/redundancy';
|
||||||
import { setAPIConfig } from '../../lib/api/config';
|
import { setAPIConfig, IconifyAPIConfig } from '../../lib/api/config';
|
||||||
import { setAPIModule, APIQueryParams } from '../../lib/api/modules';
|
import { setProviderAPIModule, APIQueryParams } from '../../lib/api/modules';
|
||||||
import { API } from '../../lib/api/';
|
import { API } from '../../lib/api/';
|
||||||
|
|
||||||
describe('Testing API loadIcons', () => {
|
describe('Testing API loadIcons', () => {
|
||||||
@ -16,24 +16,24 @@ describe('Testing API loadIcons', () => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
it('Loading few icons', done => {
|
it('Loading few icons', (done) => {
|
||||||
|
const provider = nextPrefix();
|
||||||
const prefix = nextPrefix();
|
const prefix = nextPrefix();
|
||||||
let asyncCounter = 0;
|
let asyncCounter = 0;
|
||||||
|
|
||||||
// Set config
|
// Set config
|
||||||
setAPIConfig(
|
setAPIConfig(provider, {
|
||||||
{
|
resources: ['https://api1.local', 'https://api2.local'],
|
||||||
resources: ['https://api1.local', 'https://api2.local'],
|
});
|
||||||
},
|
|
||||||
prefix
|
|
||||||
);
|
|
||||||
|
|
||||||
// Icon loader
|
// Icon loader
|
||||||
const prepareQuery = (
|
const prepareQuery = (
|
||||||
|
provider: string,
|
||||||
prefix: string,
|
prefix: string,
|
||||||
icons: string[]
|
icons: string[]
|
||||||
): APIQueryParams[] => {
|
): APIQueryParams[] => {
|
||||||
const item: APIQueryParams = {
|
const item: APIQueryParams = {
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
icons,
|
icons,
|
||||||
};
|
};
|
||||||
@ -44,6 +44,7 @@ describe('Testing API loadIcons', () => {
|
|||||||
|
|
||||||
// Test input and return as one item
|
// Test input and return as one item
|
||||||
const expected: APIQueryParams = {
|
const expected: APIQueryParams = {
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
icons: ['icon1', 'icon2'],
|
icons: ['icon1', 'icon2'],
|
||||||
};
|
};
|
||||||
@ -64,6 +65,7 @@ describe('Testing API loadIcons', () => {
|
|||||||
// Test input
|
// Test input
|
||||||
expect(host).to.be.equal('https://api1.local');
|
expect(host).to.be.equal('https://api1.local');
|
||||||
const expected: APIQueryParams = {
|
const expected: APIQueryParams = {
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
icons: ['icon1', 'icon2'],
|
icons: ['icon1', 'icon2'],
|
||||||
};
|
};
|
||||||
@ -86,24 +88,22 @@ describe('Testing API loadIcons', () => {
|
|||||||
expect(asyncCounter).to.be.equal(3);
|
expect(asyncCounter).to.be.equal(3);
|
||||||
};
|
};
|
||||||
|
|
||||||
setAPIModule(
|
setProviderAPIModule(provider, {
|
||||||
{
|
prepare: prepareQuery,
|
||||||
prepare: prepareQuery,
|
send: sendQuery,
|
||||||
send: sendQuery,
|
});
|
||||||
},
|
|
||||||
prefix
|
|
||||||
);
|
|
||||||
|
|
||||||
// Load icons
|
// Load icons
|
||||||
API.loadIcons(
|
API.loadIcons(
|
||||||
[
|
[
|
||||||
// as icon
|
// as icon
|
||||||
{
|
{
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
name: 'icon1',
|
name: 'icon1',
|
||||||
},
|
},
|
||||||
// as string
|
// as string
|
||||||
prefix + ':icon2',
|
provider + ':' + prefix + ':icon2',
|
||||||
],
|
],
|
||||||
(loaded, missing, pending, unsubscribe) => {
|
(loaded, missing, pending, unsubscribe) => {
|
||||||
// This callback should be called last
|
// This callback should be called last
|
||||||
@ -112,10 +112,12 @@ describe('Testing API loadIcons', () => {
|
|||||||
|
|
||||||
expect(loaded).to.be.eql([
|
expect(loaded).to.be.eql([
|
||||||
{
|
{
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
name: 'icon1',
|
name: 'icon1',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
name: 'icon2',
|
name: 'icon2',
|
||||||
},
|
},
|
||||||
@ -123,42 +125,54 @@ describe('Testing API loadIcons', () => {
|
|||||||
expect(missing).to.be.eql([]);
|
expect(missing).to.be.eql([]);
|
||||||
expect(pending).to.be.eql([]);
|
expect(pending).to.be.eql([]);
|
||||||
|
|
||||||
expect(API.isPending(prefix, 'icon1')).to.be.equal(false);
|
expect(
|
||||||
expect(API.isPending(prefix, 'icon3')).to.be.equal(false);
|
API.isPending({
|
||||||
|
provider,
|
||||||
|
prefix,
|
||||||
|
name: 'icon1',
|
||||||
|
})
|
||||||
|
).to.be.equal(false);
|
||||||
|
expect(
|
||||||
|
API.isPending({ provider, prefix, name: 'icon3' })
|
||||||
|
).to.be.equal(false);
|
||||||
|
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// Test isPending
|
// Test isPending
|
||||||
expect(API.isPending(prefix, 'icon1')).to.be.equal(true);
|
expect(API.isPending({ provider, prefix, name: 'icon1' })).to.be.equal(
|
||||||
expect(API.isPending(prefix, 'icon3')).to.be.equal(false);
|
true
|
||||||
|
);
|
||||||
|
expect(API.isPending({ provider, prefix, name: 'icon3' })).to.be.equal(
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
// Make sure asyncCounter wasn't increased because loading shoud happen on next tick
|
// Make sure asyncCounter wasn't increased because loading shoud happen on next tick
|
||||||
expect(asyncCounter).to.be.equal(0);
|
expect(asyncCounter).to.be.equal(0);
|
||||||
asyncCounter++;
|
asyncCounter++;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Split results', done => {
|
it('Split results', (done) => {
|
||||||
|
const provider = nextPrefix();
|
||||||
const prefix = nextPrefix();
|
const prefix = nextPrefix();
|
||||||
|
|
||||||
// Set config
|
// Set config
|
||||||
setAPIConfig(
|
setAPIConfig(provider, {
|
||||||
{
|
resources: ['https://api1.local', 'https://api2.local'],
|
||||||
resources: ['https://api1.local', 'https://api2.local'],
|
});
|
||||||
},
|
|
||||||
prefix
|
|
||||||
);
|
|
||||||
|
|
||||||
// Icon loader
|
// Icon loader
|
||||||
const prepareQuery = (
|
const prepareQuery = (
|
||||||
|
provider: string,
|
||||||
prefix: string,
|
prefix: string,
|
||||||
icons: string[]
|
icons: string[]
|
||||||
): APIQueryParams[] => {
|
): APIQueryParams[] => {
|
||||||
// Split all icons in multiple queries, one icon per query
|
// Split all icons in multiple queries, one icon per query
|
||||||
const results: APIQueryParams[] = [];
|
const results: APIQueryParams[] = [];
|
||||||
icons.forEach(icon => {
|
icons.forEach((icon) => {
|
||||||
const item: APIQueryParams = {
|
const item: APIQueryParams = {
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
icons: [icon],
|
icons: [icon],
|
||||||
};
|
};
|
||||||
@ -182,6 +196,7 @@ describe('Testing API loadIcons', () => {
|
|||||||
// Icon names should match queryCounter: 'icon1' on first run, 'icon2' on second run
|
// Icon names should match queryCounter: 'icon1' on first run, 'icon2' on second run
|
||||||
queryCounter++;
|
queryCounter++;
|
||||||
const expected: APIQueryParams = {
|
const expected: APIQueryParams = {
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
icons: ['icon' + queryCounter],
|
icons: ['icon' + queryCounter],
|
||||||
};
|
};
|
||||||
@ -189,7 +204,7 @@ describe('Testing API loadIcons', () => {
|
|||||||
|
|
||||||
// Send only requested icons
|
// Send only requested icons
|
||||||
const icons = Object.create(null);
|
const icons = Object.create(null);
|
||||||
params.icons.forEach(icon => {
|
params.icons.forEach((icon) => {
|
||||||
icons[icon] = {
|
icons[icon] = {
|
||||||
body: '<path d="" />',
|
body: '<path d="" />',
|
||||||
};
|
};
|
||||||
@ -200,18 +215,18 @@ describe('Testing API loadIcons', () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
setAPIModule(
|
setProviderAPIModule(provider, {
|
||||||
{
|
prepare: prepareQuery,
|
||||||
prepare: prepareQuery,
|
send: sendQuery,
|
||||||
send: sendQuery,
|
});
|
||||||
},
|
|
||||||
prefix
|
|
||||||
);
|
|
||||||
|
|
||||||
// Load icons
|
// Load icons
|
||||||
let callbackCalled = false;
|
let callbackCalled = false;
|
||||||
API.loadIcons(
|
API.loadIcons(
|
||||||
[prefix + ':icon1', prefix + ':icon2'],
|
[
|
||||||
|
provider + ':' + prefix + ':icon1',
|
||||||
|
provider + ':' + prefix + ':icon2',
|
||||||
|
],
|
||||||
(loaded, missing, pending, unsubscribe) => {
|
(loaded, missing, pending, unsubscribe) => {
|
||||||
// Callback should be called only once because results should be sent in same tick
|
// Callback should be called only once because results should be sent in same tick
|
||||||
expect(callbackCalled).to.be.equal(false);
|
expect(callbackCalled).to.be.equal(false);
|
||||||
@ -220,10 +235,12 @@ describe('Testing API loadIcons', () => {
|
|||||||
// Test data
|
// Test data
|
||||||
expect(loaded).to.be.eql([
|
expect(loaded).to.be.eql([
|
||||||
{
|
{
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
name: 'icon1',
|
name: 'icon1',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
name: 'icon2',
|
name: 'icon2',
|
||||||
},
|
},
|
||||||
@ -235,24 +252,24 @@ describe('Testing API loadIcons', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Fail on default host', done => {
|
it('Fail on default host', (done) => {
|
||||||
|
const provider = nextPrefix();
|
||||||
const prefix = nextPrefix();
|
const prefix = nextPrefix();
|
||||||
|
|
||||||
// Set config
|
// Set config
|
||||||
setAPIConfig(
|
setAPIConfig(provider, {
|
||||||
{
|
resources: ['https://api1.local', 'https://api2.local'],
|
||||||
resources: ['https://api1.local', 'https://api2.local'],
|
rotate: 100, // 100ms to speed up test
|
||||||
rotate: 100, // 100ms to speed up test
|
});
|
||||||
},
|
|
||||||
prefix
|
|
||||||
);
|
|
||||||
|
|
||||||
// Icon loader
|
// Icon loader
|
||||||
const prepareQuery = (
|
const prepareQuery = (
|
||||||
|
provider: string,
|
||||||
prefix: string,
|
prefix: string,
|
||||||
icons: string[]
|
icons: string[]
|
||||||
): APIQueryParams[] => {
|
): APIQueryParams[] => {
|
||||||
const item: APIQueryParams = {
|
const item: APIQueryParams = {
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
icons,
|
icons,
|
||||||
};
|
};
|
||||||
@ -299,18 +316,18 @@ describe('Testing API loadIcons', () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
setAPIModule(
|
setProviderAPIModule(provider, {
|
||||||
{
|
prepare: prepareQuery,
|
||||||
prepare: prepareQuery,
|
send: sendQuery,
|
||||||
send: sendQuery,
|
});
|
||||||
},
|
|
||||||
prefix
|
|
||||||
);
|
|
||||||
|
|
||||||
// Load icons
|
// Load icons
|
||||||
let callbackCalled = false;
|
let callbackCalled = false;
|
||||||
API.loadIcons(
|
API.loadIcons(
|
||||||
[prefix + ':icon1', prefix + ':icon2'],
|
[
|
||||||
|
provider + ':' + prefix + ':icon1',
|
||||||
|
provider + ':' + prefix + ':icon2',
|
||||||
|
],
|
||||||
(loaded, missing, pending, unsubscribe) => {
|
(loaded, missing, pending, unsubscribe) => {
|
||||||
// Callback should be called only once
|
// Callback should be called only once
|
||||||
expect(callbackCalled).to.be.equal(false);
|
expect(callbackCalled).to.be.equal(false);
|
||||||
@ -319,10 +336,12 @@ describe('Testing API loadIcons', () => {
|
|||||||
// Test data
|
// Test data
|
||||||
expect(loaded).to.be.eql([
|
expect(loaded).to.be.eql([
|
||||||
{
|
{
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
name: 'icon1',
|
name: 'icon1',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
name: 'icon2',
|
name: 'icon2',
|
||||||
},
|
},
|
||||||
@ -335,24 +354,24 @@ describe('Testing API loadIcons', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Fail on default host, multiple queries', done => {
|
it('Fail on default host, multiple queries', (done) => {
|
||||||
|
const provider = nextPrefix();
|
||||||
const prefix = nextPrefix();
|
const prefix = nextPrefix();
|
||||||
|
|
||||||
// Set config
|
// Set config
|
||||||
setAPIConfig(
|
setAPIConfig(provider, {
|
||||||
{
|
resources: ['https://api1.local', 'https://api2.local'],
|
||||||
resources: ['https://api1.local', 'https://api2.local'],
|
rotate: 100, // 100ms to speed up test
|
||||||
rotate: 100, // 100ms to speed up test
|
});
|
||||||
},
|
|
||||||
prefix
|
|
||||||
);
|
|
||||||
|
|
||||||
// Icon loader
|
// Icon loader
|
||||||
const prepareQuery = (
|
const prepareQuery = (
|
||||||
|
provider: string,
|
||||||
prefix: string,
|
prefix: string,
|
||||||
icons: string[]
|
icons: string[]
|
||||||
): APIQueryParams[] => {
|
): APIQueryParams[] => {
|
||||||
const item: APIQueryParams = {
|
const item: APIQueryParams = {
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
icons,
|
icons,
|
||||||
};
|
};
|
||||||
@ -420,18 +439,18 @@ describe('Testing API loadIcons', () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
setAPIModule(
|
setProviderAPIModule(provider, {
|
||||||
{
|
prepare: prepareQuery,
|
||||||
prepare: prepareQuery,
|
send: sendQuery,
|
||||||
send: sendQuery,
|
});
|
||||||
},
|
|
||||||
prefix
|
|
||||||
);
|
|
||||||
|
|
||||||
// Load icons
|
// Load icons
|
||||||
let callbackCalled = false;
|
let callbackCalled = false;
|
||||||
API.loadIcons(
|
API.loadIcons(
|
||||||
[prefix + ':icon1', prefix + ':icon2'],
|
[
|
||||||
|
provider + ':' + prefix + ':icon1',
|
||||||
|
provider + ':' + prefix + ':icon2',
|
||||||
|
],
|
||||||
(loaded, missing, pending, unsubscribe) => {
|
(loaded, missing, pending, unsubscribe) => {
|
||||||
// Callback should be called only once
|
// Callback should be called only once
|
||||||
expect(callbackCalled).to.be.equal(false);
|
expect(callbackCalled).to.be.equal(false);
|
||||||
@ -440,10 +459,12 @@ describe('Testing API loadIcons', () => {
|
|||||||
// Test data
|
// Test data
|
||||||
expect(loaded).to.be.eql([
|
expect(loaded).to.be.eql([
|
||||||
{
|
{
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
name: 'icon1',
|
name: 'icon1',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
name: 'icon2',
|
name: 'icon2',
|
||||||
},
|
},
|
||||||
@ -455,7 +476,10 @@ describe('Testing API loadIcons', () => {
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
let callbackCalled = false;
|
let callbackCalled = false;
|
||||||
API.loadIcons(
|
API.loadIcons(
|
||||||
[prefix + ':icon3', prefix + ':icon4'],
|
[
|
||||||
|
provider + ':' + prefix + ':icon3',
|
||||||
|
provider + ':' + prefix + ':icon4',
|
||||||
|
],
|
||||||
(loaded, missing, pending, unsubscribe) => {
|
(loaded, missing, pending, unsubscribe) => {
|
||||||
// Callback should be called only once
|
// Callback should be called only once
|
||||||
expect(callbackCalled).to.be.equal(false);
|
expect(callbackCalled).to.be.equal(false);
|
||||||
@ -464,10 +488,12 @@ describe('Testing API loadIcons', () => {
|
|||||||
// Test data
|
// Test data
|
||||||
expect(loaded).to.be.eql([
|
expect(loaded).to.be.eql([
|
||||||
{
|
{
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
name: 'icon3',
|
name: 'icon3',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
name: 'icon4',
|
name: 'icon4',
|
||||||
},
|
},
|
||||||
@ -483,25 +509,25 @@ describe('Testing API loadIcons', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Fail on default host, multiple queries with different prefixes', done => {
|
it('Fail on default host, multiple queries with different prefixes', (done) => {
|
||||||
|
const provider = nextPrefix();
|
||||||
const prefix = nextPrefix();
|
const prefix = nextPrefix();
|
||||||
const prefix2 = nextPrefix();
|
const prefix2 = nextPrefix();
|
||||||
|
|
||||||
// Set config
|
// Set config
|
||||||
setAPIConfig(
|
setAPIConfig(provider, {
|
||||||
{
|
resources: ['https://api1.local', 'https://api2.local'],
|
||||||
resources: ['https://api1.local', 'https://api2.local'],
|
rotate: 100, // 100ms to speed up test
|
||||||
rotate: 100, // 100ms to speed up test
|
});
|
||||||
},
|
|
||||||
[prefix, prefix2]
|
|
||||||
);
|
|
||||||
|
|
||||||
// Icon loader
|
// Icon loader
|
||||||
const prepareQuery = (
|
const prepareQuery = (
|
||||||
|
provider: string,
|
||||||
prefix: string,
|
prefix: string,
|
||||||
icons: string[]
|
icons: string[]
|
||||||
): APIQueryParams[] => {
|
): APIQueryParams[] => {
|
||||||
const item: APIQueryParams = {
|
const item: APIQueryParams = {
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
icons,
|
icons,
|
||||||
};
|
};
|
||||||
@ -572,18 +598,18 @@ describe('Testing API loadIcons', () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
setAPIModule(
|
setProviderAPIModule(provider, {
|
||||||
{
|
prepare: prepareQuery,
|
||||||
prepare: prepareQuery,
|
send: sendQuery,
|
||||||
send: sendQuery,
|
});
|
||||||
},
|
|
||||||
[prefix, prefix2]
|
|
||||||
);
|
|
||||||
|
|
||||||
// Load icons
|
// Load icons
|
||||||
let callbackCalled = false;
|
let callbackCalled = false;
|
||||||
API.loadIcons(
|
API.loadIcons(
|
||||||
[prefix + ':icon1', prefix + ':icon2'],
|
[
|
||||||
|
provider + ':' + prefix + ':icon1',
|
||||||
|
provider + ':' + prefix + ':icon2',
|
||||||
|
],
|
||||||
(loaded, missing, pending, unsubscribe) => {
|
(loaded, missing, pending, unsubscribe) => {
|
||||||
// Callback should be called only once
|
// Callback should be called only once
|
||||||
expect(callbackCalled).to.be.equal(false);
|
expect(callbackCalled).to.be.equal(false);
|
||||||
@ -592,10 +618,12 @@ describe('Testing API loadIcons', () => {
|
|||||||
// Test data
|
// Test data
|
||||||
expect(loaded).to.be.eql([
|
expect(loaded).to.be.eql([
|
||||||
{
|
{
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
name: 'icon1',
|
name: 'icon1',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
name: 'icon2',
|
name: 'icon2',
|
||||||
},
|
},
|
||||||
@ -607,7 +635,10 @@ describe('Testing API loadIcons', () => {
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
let callbackCalled = false;
|
let callbackCalled = false;
|
||||||
API.loadIcons(
|
API.loadIcons(
|
||||||
[prefix2 + ':icon2', prefix2 + ':icon4'],
|
[
|
||||||
|
provider + ':' + prefix2 + ':icon2',
|
||||||
|
provider + ':' + prefix2 + ':icon4',
|
||||||
|
],
|
||||||
(loaded, missing, pending, unsubscribe) => {
|
(loaded, missing, pending, unsubscribe) => {
|
||||||
// Callback should be called only once
|
// Callback should be called only once
|
||||||
expect(callbackCalled).to.be.equal(false);
|
expect(callbackCalled).to.be.equal(false);
|
||||||
@ -616,10 +647,12 @@ describe('Testing API loadIcons', () => {
|
|||||||
// Test data
|
// Test data
|
||||||
expect(loaded).to.be.eql([
|
expect(loaded).to.be.eql([
|
||||||
{
|
{
|
||||||
|
provider,
|
||||||
prefix: prefix2,
|
prefix: prefix2,
|
||||||
name: 'icon2',
|
name: 'icon2',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
provider,
|
||||||
prefix: prefix2,
|
prefix: prefix2,
|
||||||
name: 'icon4',
|
name: 'icon4',
|
||||||
},
|
},
|
||||||
|
@ -14,6 +14,8 @@ import {
|
|||||||
} from './fake_cache';
|
} from './fake_cache';
|
||||||
|
|
||||||
describe('Testing mocked localStorage', () => {
|
describe('Testing mocked localStorage', () => {
|
||||||
|
const provider = '';
|
||||||
|
|
||||||
it('No usable cache', () => {
|
it('No usable cache', () => {
|
||||||
reset({});
|
reset({});
|
||||||
|
|
||||||
@ -85,6 +87,7 @@ describe('Testing mocked localStorage', () => {
|
|||||||
cachePrefix + '0',
|
cachePrefix + '0',
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
cached: Date.now(),
|
cached: Date.now(),
|
||||||
|
provider,
|
||||||
data: {
|
data: {
|
||||||
prefix: prefix,
|
prefix: prefix,
|
||||||
icons: {
|
icons: {
|
||||||
@ -143,6 +146,7 @@ describe('Testing mocked localStorage', () => {
|
|||||||
cachePrefix + '0',
|
cachePrefix + '0',
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
cached: Date.now(),
|
cached: Date.now(),
|
||||||
|
provider,
|
||||||
data: {
|
data: {
|
||||||
prefix: prefix,
|
prefix: prefix,
|
||||||
icons: {
|
icons: {
|
||||||
|
@ -24,6 +24,8 @@ import {
|
|||||||
import { IconifyIcon, IconifyJSON } from '@iconify/types';
|
import { IconifyIcon, IconifyJSON } from '@iconify/types';
|
||||||
|
|
||||||
describe('Testing loading from localStorage', () => {
|
describe('Testing loading from localStorage', () => {
|
||||||
|
const provider = '';
|
||||||
|
|
||||||
it('Valid icon set', () => {
|
it('Valid icon set', () => {
|
||||||
const prefix = nextPrefix();
|
const prefix = nextPrefix();
|
||||||
const cache = createCache();
|
const cache = createCache();
|
||||||
@ -34,6 +36,7 @@ describe('Testing loading from localStorage', () => {
|
|||||||
|
|
||||||
const item: StoredItem = {
|
const item: StoredItem = {
|
||||||
cached: Math.floor(Date.now() / hour),
|
cached: Math.floor(Date.now() / hour),
|
||||||
|
provider,
|
||||||
data: {
|
data: {
|
||||||
prefix: prefix,
|
prefix: prefix,
|
||||||
icons: {
|
icons: {
|
||||||
@ -51,7 +54,7 @@ describe('Testing loading from localStorage', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Check icon storage
|
// Check icon storage
|
||||||
const icons = getStorage(prefix);
|
const icons = getStorage(provider, prefix);
|
||||||
expect(iconExists(icons, 'foo')).to.be.equal(false);
|
expect(iconExists(icons, 'foo')).to.be.equal(false);
|
||||||
|
|
||||||
// Load localStorage
|
// Load localStorage
|
||||||
@ -75,6 +78,64 @@ describe('Testing loading from localStorage', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Different provider', () => {
|
||||||
|
const provider = nextPrefix();
|
||||||
|
const prefix = nextPrefix();
|
||||||
|
const cache = createCache();
|
||||||
|
|
||||||
|
// Add one icon set
|
||||||
|
cache.setItem(versionKey, cacheVersion);
|
||||||
|
cache.setItem(countKey, '1');
|
||||||
|
|
||||||
|
const item: StoredItem = {
|
||||||
|
cached: Math.floor(Date.now() / hour),
|
||||||
|
provider,
|
||||||
|
data: {
|
||||||
|
prefix: prefix,
|
||||||
|
icons: {
|
||||||
|
foo: {
|
||||||
|
body: '<g></g>',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
cache.setItem(cachePrefix + '0', JSON.stringify(item));
|
||||||
|
|
||||||
|
// Set cache
|
||||||
|
reset({
|
||||||
|
localStorage: cache,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Check icon storage
|
||||||
|
const icons = getStorage(provider, prefix);
|
||||||
|
expect(iconExists(icons, 'foo')).to.be.equal(false);
|
||||||
|
|
||||||
|
// Check default provider
|
||||||
|
const icons2 = getStorage('', prefix);
|
||||||
|
expect(iconExists(icons2, 'foo')).to.be.equal(false);
|
||||||
|
|
||||||
|
// Load localStorage
|
||||||
|
loadCache();
|
||||||
|
|
||||||
|
// Icon should exist now
|
||||||
|
expect(iconExists(icons, 'foo')).to.be.equal(true);
|
||||||
|
expect(iconExists(icons2, 'foo')).to.be.equal(false);
|
||||||
|
|
||||||
|
// Check data
|
||||||
|
expect(config).to.be.eql({
|
||||||
|
local: true,
|
||||||
|
session: false,
|
||||||
|
});
|
||||||
|
expect(count).to.be.eql({
|
||||||
|
local: 1,
|
||||||
|
session: 0,
|
||||||
|
});
|
||||||
|
expect(emptyList).to.be.eql({
|
||||||
|
local: [],
|
||||||
|
session: [],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('Expired icon set', () => {
|
it('Expired icon set', () => {
|
||||||
const prefix = nextPrefix();
|
const prefix = nextPrefix();
|
||||||
const cache = createCache();
|
const cache = createCache();
|
||||||
@ -86,6 +147,7 @@ describe('Testing loading from localStorage', () => {
|
|||||||
const item: StoredItem = {
|
const item: StoredItem = {
|
||||||
// Expiration date
|
// Expiration date
|
||||||
cached: Math.floor(Date.now() / hour) - cacheExpiration - 1,
|
cached: Math.floor(Date.now() / hour) - cacheExpiration - 1,
|
||||||
|
provider,
|
||||||
data: {
|
data: {
|
||||||
prefix: prefix,
|
prefix: prefix,
|
||||||
icons: {
|
icons: {
|
||||||
@ -103,7 +165,7 @@ describe('Testing loading from localStorage', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Check icon storage
|
// Check icon storage
|
||||||
const icons = getStorage(prefix);
|
const icons = getStorage(provider, prefix);
|
||||||
expect(iconExists(icons, 'foo')).to.be.equal(false);
|
expect(iconExists(icons, 'foo')).to.be.equal(false);
|
||||||
|
|
||||||
// Load localStorage
|
// Load localStorage
|
||||||
@ -138,6 +200,7 @@ describe('Testing loading from localStorage', () => {
|
|||||||
cachePrefix + '0',
|
cachePrefix + '0',
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
cached: Math.floor(Date.now() / hour),
|
cached: Math.floor(Date.now() / hour),
|
||||||
|
provider,
|
||||||
data: {
|
data: {
|
||||||
prefix: prefix,
|
prefix: prefix,
|
||||||
icons: {
|
icons: {
|
||||||
@ -156,7 +219,7 @@ describe('Testing loading from localStorage', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Check icon storage
|
// Check icon storage
|
||||||
const icons = getStorage(prefix);
|
const icons = getStorage(provider, prefix);
|
||||||
expect(iconExists(icons, 'foo')).to.be.equal(false);
|
expect(iconExists(icons, 'foo')).to.be.equal(false);
|
||||||
|
|
||||||
// Load localStorage
|
// Load localStorage
|
||||||
@ -190,6 +253,7 @@ describe('Testing loading from localStorage', () => {
|
|||||||
|
|
||||||
const item: StoredItem = {
|
const item: StoredItem = {
|
||||||
cached: Math.floor(Date.now() / hour),
|
cached: Math.floor(Date.now() / hour),
|
||||||
|
provider,
|
||||||
data: {
|
data: {
|
||||||
prefix: prefix,
|
prefix: prefix,
|
||||||
icons: {
|
icons: {
|
||||||
@ -207,7 +271,7 @@ describe('Testing loading from localStorage', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Check icon storage
|
// Check icon storage
|
||||||
const icons = getStorage(prefix);
|
const icons = getStorage(provider, prefix);
|
||||||
expect(iconExists(icons, 'foo')).to.be.equal(false);
|
expect(iconExists(icons, 'foo')).to.be.equal(false);
|
||||||
|
|
||||||
// Load localStorage
|
// Load localStorage
|
||||||
@ -241,6 +305,7 @@ describe('Testing loading from localStorage', () => {
|
|||||||
|
|
||||||
const item: StoredItem = {
|
const item: StoredItem = {
|
||||||
cached: Math.floor(Date.now() / hour),
|
cached: Math.floor(Date.now() / hour),
|
||||||
|
provider,
|
||||||
data: {
|
data: {
|
||||||
prefix: prefix,
|
prefix: prefix,
|
||||||
icons: {
|
icons: {
|
||||||
@ -258,7 +323,7 @@ describe('Testing loading from localStorage', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Check icon storage
|
// Check icon storage
|
||||||
const icons = getStorage(prefix);
|
const icons = getStorage(provider, prefix);
|
||||||
expect(iconExists(icons, 'foo')).to.be.equal(false);
|
expect(iconExists(icons, 'foo')).to.be.equal(false);
|
||||||
|
|
||||||
// Load localStorage
|
// Load localStorage
|
||||||
@ -293,6 +358,7 @@ describe('Testing loading from localStorage', () => {
|
|||||||
// Missing: 0, 2, 3
|
// Missing: 0, 2, 3
|
||||||
const item1: StoredItem = {
|
const item1: StoredItem = {
|
||||||
cached: Math.floor(Date.now() / hour),
|
cached: Math.floor(Date.now() / hour),
|
||||||
|
provider,
|
||||||
data: {
|
data: {
|
||||||
prefix: prefix,
|
prefix: prefix,
|
||||||
icons: {
|
icons: {
|
||||||
@ -304,6 +370,7 @@ describe('Testing loading from localStorage', () => {
|
|||||||
};
|
};
|
||||||
const item4: StoredItem = {
|
const item4: StoredItem = {
|
||||||
cached: Math.floor(Date.now() / hour),
|
cached: Math.floor(Date.now() / hour),
|
||||||
|
provider,
|
||||||
data: {
|
data: {
|
||||||
prefix: prefix,
|
prefix: prefix,
|
||||||
icons: {
|
icons: {
|
||||||
@ -323,7 +390,7 @@ describe('Testing loading from localStorage', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Check icon storage
|
// Check icon storage
|
||||||
const icons = getStorage(prefix);
|
const icons = getStorage(provider, prefix);
|
||||||
expect(iconExists(icons, 'foo1')).to.be.equal(false);
|
expect(iconExists(icons, 'foo1')).to.be.equal(false);
|
||||||
expect(iconExists(icons, 'foo4')).to.be.equal(false);
|
expect(iconExists(icons, 'foo4')).to.be.equal(false);
|
||||||
|
|
||||||
@ -376,6 +443,7 @@ describe('Testing loading from localStorage', () => {
|
|||||||
};
|
};
|
||||||
const item: StoredItem = {
|
const item: StoredItem = {
|
||||||
cached: Math.floor(Date.now() / hour),
|
cached: Math.floor(Date.now() / hour),
|
||||||
|
provider,
|
||||||
data: icon,
|
data: icon,
|
||||||
};
|
};
|
||||||
icons.push(icon);
|
icons.push(icon);
|
||||||
@ -399,7 +467,7 @@ describe('Testing loading from localStorage', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Check icon storage
|
// Check icon storage
|
||||||
const iconsStorage = getStorage(prefix);
|
const iconsStorage = getStorage(provider, prefix);
|
||||||
for (let i = 0; i < 6; i++) {
|
for (let i = 0; i < 6; i++) {
|
||||||
expect(iconExists(iconsStorage, 'foo' + i)).to.be.equal(
|
expect(iconExists(iconsStorage, 'foo' + i)).to.be.equal(
|
||||||
false,
|
false,
|
||||||
|
@ -25,6 +25,8 @@ import {
|
|||||||
import { IconifyJSON } from '@iconify/types';
|
import { IconifyJSON } from '@iconify/types';
|
||||||
|
|
||||||
describe('Testing saving to localStorage', () => {
|
describe('Testing saving to localStorage', () => {
|
||||||
|
const provider = '';
|
||||||
|
|
||||||
it('One icon set', () => {
|
it('One icon set', () => {
|
||||||
const prefix = nextPrefix();
|
const prefix = nextPrefix();
|
||||||
const cache = createCache();
|
const cache = createCache();
|
||||||
@ -40,6 +42,7 @@ describe('Testing saving to localStorage', () => {
|
|||||||
};
|
};
|
||||||
const item: StoredItem = {
|
const item: StoredItem = {
|
||||||
cached: Math.floor(Date.now() / hour),
|
cached: Math.floor(Date.now() / hour),
|
||||||
|
provider,
|
||||||
data: icon,
|
data: icon,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -49,11 +52,11 @@ describe('Testing saving to localStorage', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Check icon storage
|
// Check icon storage
|
||||||
const icons = getStorage(prefix);
|
const icons = getStorage(provider, prefix);
|
||||||
expect(iconExists(icons, 'foo')).to.be.equal(false);
|
expect(iconExists(icons, 'foo')).to.be.equal(false);
|
||||||
|
|
||||||
// Save item
|
// Save item
|
||||||
storeCache(icon);
|
storeCache(provider, icon);
|
||||||
|
|
||||||
// Storing in cache should not add item to storage
|
// Storing in cache should not add item to storage
|
||||||
expect(iconExists(icons, 'foo')).to.be.equal(false);
|
expect(iconExists(icons, 'foo')).to.be.equal(false);
|
||||||
@ -96,6 +99,7 @@ describe('Testing saving to localStorage', () => {
|
|||||||
};
|
};
|
||||||
const item0: StoredItem = {
|
const item0: StoredItem = {
|
||||||
cached: Math.floor(Date.now() / hour),
|
cached: Math.floor(Date.now() / hour),
|
||||||
|
provider,
|
||||||
data: icon0,
|
data: icon0,
|
||||||
};
|
};
|
||||||
const icon1: IconifyJSON = {
|
const icon1: IconifyJSON = {
|
||||||
@ -108,6 +112,7 @@ describe('Testing saving to localStorage', () => {
|
|||||||
};
|
};
|
||||||
const item1: StoredItem = {
|
const item1: StoredItem = {
|
||||||
cached: Math.floor(Date.now() / hour),
|
cached: Math.floor(Date.now() / hour),
|
||||||
|
provider,
|
||||||
data: icon1,
|
data: icon1,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -117,8 +122,8 @@ describe('Testing saving to localStorage', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Save items
|
// Save items
|
||||||
storeCache(icon0);
|
storeCache(provider, icon0);
|
||||||
storeCache(icon1);
|
storeCache(provider, icon1);
|
||||||
|
|
||||||
// Check data that should have been updated because storeCache()
|
// Check data that should have been updated because storeCache()
|
||||||
// should call load function before first execution
|
// should call load function before first execution
|
||||||
@ -161,6 +166,7 @@ describe('Testing saving to localStorage', () => {
|
|||||||
};
|
};
|
||||||
const item0: StoredItem = {
|
const item0: StoredItem = {
|
||||||
cached: Math.floor(Date.now() / hour),
|
cached: Math.floor(Date.now() / hour),
|
||||||
|
provider,
|
||||||
data: icon0,
|
data: icon0,
|
||||||
};
|
};
|
||||||
const icon1: IconifyJSON = {
|
const icon1: IconifyJSON = {
|
||||||
@ -173,6 +179,7 @@ describe('Testing saving to localStorage', () => {
|
|||||||
};
|
};
|
||||||
const item1: StoredItem = {
|
const item1: StoredItem = {
|
||||||
cached: Math.floor(Date.now() / hour),
|
cached: Math.floor(Date.now() / hour),
|
||||||
|
provider,
|
||||||
data: icon1,
|
data: icon1,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -204,7 +211,7 @@ describe('Testing saving to localStorage', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Save items
|
// Save items
|
||||||
storeCache(icon0);
|
storeCache(provider, icon0);
|
||||||
|
|
||||||
// Check data
|
// Check data
|
||||||
expect(count).to.be.eql({
|
expect(count).to.be.eql({
|
||||||
@ -245,6 +252,7 @@ describe('Testing saving to localStorage', () => {
|
|||||||
};
|
};
|
||||||
const item: StoredItem = {
|
const item: StoredItem = {
|
||||||
cached: Math.floor(Date.now() / hour),
|
cached: Math.floor(Date.now() / hour),
|
||||||
|
provider,
|
||||||
data: icon,
|
data: icon,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -313,7 +321,7 @@ describe('Testing saving to localStorage', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Add item 5
|
// Add item 5
|
||||||
storeCache(icons[5]);
|
storeCache(provider, icons[5]);
|
||||||
expect(count).to.be.eql({
|
expect(count).to.be.eql({
|
||||||
local: 0,
|
local: 0,
|
||||||
session: 9,
|
session: 9,
|
||||||
@ -328,7 +336,7 @@ describe('Testing saving to localStorage', () => {
|
|||||||
const list = [4, 2, 1];
|
const list = [4, 2, 1];
|
||||||
list.slice(0).forEach((index) => {
|
list.slice(0).forEach((index) => {
|
||||||
expect(list.shift()).to.be.equal(index);
|
expect(list.shift()).to.be.equal(index);
|
||||||
storeCache(icons[index]);
|
storeCache(provider, icons[index]);
|
||||||
expect(count).to.be.eql({
|
expect(count).to.be.eql({
|
||||||
local: 0,
|
local: 0,
|
||||||
session: 9,
|
session: 9,
|
||||||
@ -341,7 +349,7 @@ describe('Testing saving to localStorage', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Add item 10
|
// Add item 10
|
||||||
storeCache(icons[10]);
|
storeCache(provider, icons[10]);
|
||||||
expect(count).to.be.eql({
|
expect(count).to.be.eql({
|
||||||
local: 0,
|
local: 0,
|
||||||
session: 10,
|
session: 10,
|
||||||
@ -353,7 +361,7 @@ describe('Testing saving to localStorage', () => {
|
|||||||
expect(cache.getItem(countKey)).to.be.equal('10');
|
expect(cache.getItem(countKey)).to.be.equal('10');
|
||||||
|
|
||||||
// Add item 11
|
// Add item 11
|
||||||
storeCache(icons[11]);
|
storeCache(provider, icons[11]);
|
||||||
expect(count).to.be.eql({
|
expect(count).to.be.eql({
|
||||||
local: 0,
|
local: 0,
|
||||||
session: 11,
|
session: 11,
|
||||||
@ -392,7 +400,7 @@ describe('Testing saving to localStorage', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Check icon storage
|
// Check icon storage
|
||||||
const icons = getStorage(prefix);
|
const icons = getStorage(provider, prefix);
|
||||||
expect(iconExists(icons, 'foo1')).to.be.equal(false);
|
expect(iconExists(icons, 'foo1')).to.be.equal(false);
|
||||||
|
|
||||||
// Load cache
|
// Load cache
|
||||||
@ -422,11 +430,12 @@ describe('Testing saving to localStorage', () => {
|
|||||||
};
|
};
|
||||||
const item: StoredItem = {
|
const item: StoredItem = {
|
||||||
cached: Math.floor(Date.now() / hour),
|
cached: Math.floor(Date.now() / hour),
|
||||||
|
provider,
|
||||||
data: icon,
|
data: icon,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Save item
|
// Save item
|
||||||
storeCache(icon);
|
storeCache(provider, icon);
|
||||||
|
|
||||||
// Storing in cache should not add item to storage
|
// Storing in cache should not add item to storage
|
||||||
expect(iconExists(icons, 'foo')).to.be.equal(false);
|
expect(iconExists(icons, 'foo')).to.be.equal(false);
|
||||||
@ -473,6 +482,7 @@ describe('Testing saving to localStorage', () => {
|
|||||||
};
|
};
|
||||||
const item: StoredItem = {
|
const item: StoredItem = {
|
||||||
cached: Math.floor(Date.now() / hour),
|
cached: Math.floor(Date.now() / hour),
|
||||||
|
provider,
|
||||||
data: icon,
|
data: icon,
|
||||||
};
|
};
|
||||||
cache1.setItem(cachePrefix + index, JSON.stringify(item));
|
cache1.setItem(cachePrefix + index, JSON.stringify(item));
|
||||||
@ -492,6 +502,7 @@ describe('Testing saving to localStorage', () => {
|
|||||||
};
|
};
|
||||||
const item: StoredItem = {
|
const item: StoredItem = {
|
||||||
cached: Math.floor(Date.now() / hour),
|
cached: Math.floor(Date.now() / hour),
|
||||||
|
provider,
|
||||||
data: icon,
|
data: icon,
|
||||||
};
|
};
|
||||||
cache2.setItem(cachePrefix + index, JSON.stringify(item));
|
cache2.setItem(cachePrefix + index, JSON.stringify(item));
|
||||||
@ -521,7 +532,7 @@ describe('Testing saving to localStorage', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Check icon storage
|
// Check icon storage
|
||||||
const iconsStorage = getStorage(prefix);
|
const iconsStorage = getStorage(provider, prefix);
|
||||||
for (let i = 0; i < count.local; i++) {
|
for (let i = 0; i < count.local; i++) {
|
||||||
expect(iconExists(iconsStorage, 'foo' + i)).to.be.equal(
|
expect(iconExists(iconsStorage, 'foo' + i)).to.be.equal(
|
||||||
true,
|
true,
|
||||||
@ -546,9 +557,10 @@ describe('Testing saving to localStorage', () => {
|
|||||||
};
|
};
|
||||||
const item: StoredItem = {
|
const item: StoredItem = {
|
||||||
cached: Math.floor(Date.now() / hour),
|
cached: Math.floor(Date.now() / hour),
|
||||||
|
provider,
|
||||||
data: icon,
|
data: icon,
|
||||||
};
|
};
|
||||||
storeCache(icon);
|
storeCache(provider, icon);
|
||||||
|
|
||||||
// Check data
|
// Check data
|
||||||
expect(count).to.be.eql({
|
expect(count).to.be.eql({
|
||||||
@ -585,6 +597,7 @@ describe('Testing saving to localStorage', () => {
|
|||||||
};
|
};
|
||||||
const item: StoredItem = {
|
const item: StoredItem = {
|
||||||
cached: Math.floor(Date.now() / hour),
|
cached: Math.floor(Date.now() / hour),
|
||||||
|
provider,
|
||||||
data: icon,
|
data: icon,
|
||||||
};
|
};
|
||||||
cache1.setItem(cachePrefix + index, JSON.stringify(item));
|
cache1.setItem(cachePrefix + index, JSON.stringify(item));
|
||||||
@ -604,6 +617,7 @@ describe('Testing saving to localStorage', () => {
|
|||||||
};
|
};
|
||||||
const item: StoredItem = {
|
const item: StoredItem = {
|
||||||
cached: Math.floor(Date.now() / hour),
|
cached: Math.floor(Date.now() / hour),
|
||||||
|
provider,
|
||||||
data: icon,
|
data: icon,
|
||||||
};
|
};
|
||||||
cache2.setItem(cachePrefix + index, JSON.stringify(item));
|
cache2.setItem(cachePrefix + index, JSON.stringify(item));
|
||||||
@ -633,7 +647,7 @@ describe('Testing saving to localStorage', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Check icon storage
|
// Check icon storage
|
||||||
const iconsStorage = getStorage(prefix);
|
const iconsStorage = getStorage(provider, prefix);
|
||||||
for (let i = 0; i < count.local; i++) {
|
for (let i = 0; i < count.local; i++) {
|
||||||
expect(iconExists(iconsStorage, 'foo' + i)).to.be.equal(
|
expect(iconExists(iconsStorage, 'foo' + i)).to.be.equal(
|
||||||
true,
|
true,
|
||||||
@ -661,9 +675,10 @@ describe('Testing saving to localStorage', () => {
|
|||||||
};
|
};
|
||||||
const item: StoredItem = {
|
const item: StoredItem = {
|
||||||
cached: Math.floor(Date.now() / hour),
|
cached: Math.floor(Date.now() / hour),
|
||||||
|
provider,
|
||||||
data: icon,
|
data: icon,
|
||||||
};
|
};
|
||||||
storeCache(icon);
|
storeCache(provider, icon);
|
||||||
|
|
||||||
// Check data
|
// Check data
|
||||||
expect(count).to.be.eql({
|
expect(count).to.be.eql({
|
||||||
|
@ -9,7 +9,7 @@ export function nextPrefix(): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Cache version. Bump when structure changes
|
// Cache version. Bump when structure changes
|
||||||
export const cacheVersion = 'iconify1';
|
export const cacheVersion = 'iconify2';
|
||||||
|
|
||||||
// Cache keys
|
// Cache keys
|
||||||
export const cachePrefix = 'iconify';
|
export const cachePrefix = 'iconify';
|
||||||
|
@ -19,6 +19,7 @@ import {
|
|||||||
getIcon,
|
getIcon,
|
||||||
addIcon,
|
addIcon,
|
||||||
addIconSet,
|
addIconSet,
|
||||||
|
listStoredProviders,
|
||||||
listStoredPrefixes,
|
listStoredPrefixes,
|
||||||
} from '@iconify/core/lib/storage';
|
} from '@iconify/core/lib/storage';
|
||||||
import { iconToSVG, IconifyIconBuildResult } from '@iconify/core/lib/builder';
|
import { iconToSVG, IconifyIconBuildResult } from '@iconify/core/lib/builder';
|
||||||
@ -39,7 +40,7 @@ import { storeCache, loadCache, config } from '@iconify/core/lib/cache/storage';
|
|||||||
|
|
||||||
// API
|
// API
|
||||||
import { API } from '@iconify/core/lib/api/';
|
import { API } from '@iconify/core/lib/api/';
|
||||||
import { setAPIModule } from '@iconify/core/lib/api/modules';
|
import { setDefaultAPIModule } from '@iconify/core/lib/api/modules';
|
||||||
import { setAPIConfig, IconifyAPIConfig } from '@iconify/core/lib/api/config';
|
import { setAPIConfig, IconifyAPIConfig } from '@iconify/core/lib/api/config';
|
||||||
import { prepareQuery, sendQuery } from './modules/api-jsonp';
|
import { prepareQuery, sendQuery } from './modules/api-jsonp';
|
||||||
import {
|
import {
|
||||||
@ -105,7 +106,7 @@ export interface IconifyGlobal {
|
|||||||
/**
|
/**
|
||||||
* List all available icons
|
* List all available icons
|
||||||
*/
|
*/
|
||||||
listIcons: (prefix?: string) => string[];
|
listIcons: (provider?: string, prefix?: string) => string[];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load icons
|
* Load icons
|
||||||
@ -157,7 +158,7 @@ export interface IconifyGlobal {
|
|||||||
/**
|
/**
|
||||||
* Add icon set to storage
|
* Add icon set to storage
|
||||||
*/
|
*/
|
||||||
addCollection: (data: IconifyJSON) => boolean;
|
addCollection: (data: IconifyJSON, provider?: string) => boolean;
|
||||||
|
|
||||||
/* API stuff */
|
/* API stuff */
|
||||||
/**
|
/**
|
||||||
@ -174,8 +175,8 @@ export interface IconifyGlobal {
|
|||||||
* Set API configuration
|
* Set API configuration
|
||||||
*/
|
*/
|
||||||
setAPIConfig: (
|
setAPIConfig: (
|
||||||
customConfig: Partial<IconifyAPIConfig>,
|
provider: string,
|
||||||
prefix?: string | string[]
|
customConfig: Partial<IconifyAPIConfig>
|
||||||
) => void;
|
) => void;
|
||||||
|
|
||||||
/* Scan DOM */
|
/* Scan DOM */
|
||||||
@ -211,7 +212,9 @@ function getIconName(name: string): IconifyIconName | null {
|
|||||||
*/
|
*/
|
||||||
function getIconData(name: string): FullIconifyIcon | null {
|
function getIconData(name: string): FullIconifyIcon | null {
|
||||||
const icon = getIconName(name);
|
const icon = getIconName(name);
|
||||||
return icon ? getIcon(getStorage(icon.prefix), icon.name) : null;
|
return icon
|
||||||
|
? getIcon(getStorage(icon.provider, icon.prefix), icon.name)
|
||||||
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -282,23 +285,38 @@ const Iconify: IconifyGlobal = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// List icons
|
// List icons
|
||||||
listIcons: (prefix?: string) => {
|
listIcons: (provider?: string, prefix?: string) => {
|
||||||
let icons = [];
|
let icons = [];
|
||||||
|
|
||||||
let prefixes = listStoredPrefixes();
|
// Get providers
|
||||||
let addPrefix = true;
|
let providers: string[];
|
||||||
if (typeof prefix === 'string') {
|
if (typeof provider === 'string') {
|
||||||
prefixes = prefixes.indexOf(prefix) !== -1 ? [] : [prefix];
|
providers = [provider];
|
||||||
addPrefix = false;
|
} else {
|
||||||
|
providers = listStoredProviders();
|
||||||
}
|
}
|
||||||
|
|
||||||
prefixes.forEach((prefix) => {
|
// Get all icons
|
||||||
const storage = getStorage(prefix);
|
providers.forEach((provider) => {
|
||||||
let icons = Object.keys(storage.icons);
|
let prefixes: string[];
|
||||||
if (addPrefix) {
|
|
||||||
icons = icons.map((name) => prefix + ':' + name);
|
if (typeof prefix === 'string') {
|
||||||
|
prefixes = [prefix];
|
||||||
|
} else {
|
||||||
|
prefixes = listStoredPrefixes(provider);
|
||||||
}
|
}
|
||||||
icons = icons.concat(icons);
|
|
||||||
|
prefixes.forEach((prefix) => {
|
||||||
|
const storage = getStorage(provider, prefix);
|
||||||
|
let icons = Object.keys(storage.icons).map(
|
||||||
|
(name) =>
|
||||||
|
(provider !== '' ? '@' + provider + ':' : '') +
|
||||||
|
prefix +
|
||||||
|
':' +
|
||||||
|
name
|
||||||
|
);
|
||||||
|
icons = icons.concat(icons);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
return icons;
|
return icons;
|
||||||
@ -331,16 +349,21 @@ const Iconify: IconifyGlobal = {
|
|||||||
if (!icon) {
|
if (!icon) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const storage = getStorage(icon.prefix);
|
const storage = getStorage(icon.provider, icon.prefix);
|
||||||
return addIcon(storage, icon.name, data);
|
return addIcon(storage, icon.name, data);
|
||||||
},
|
},
|
||||||
|
|
||||||
// Add icon set
|
// Add icon set
|
||||||
addCollection: (data) => {
|
addCollection: (data, provider?: string) => {
|
||||||
|
if (typeof provider !== 'string') {
|
||||||
|
provider = '';
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
typeof data !== 'object' ||
|
typeof data !== 'object' ||
|
||||||
typeof data.prefix !== 'string' ||
|
typeof data.prefix !== 'string' ||
|
||||||
!validateIcon({
|
!validateIcon({
|
||||||
|
provider,
|
||||||
prefix: data.prefix,
|
prefix: data.prefix,
|
||||||
name: 'a',
|
name: 'a',
|
||||||
})
|
})
|
||||||
@ -348,7 +371,7 @@ const Iconify: IconifyGlobal = {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const storage = getStorage(data.prefix);
|
const storage = getStorage(provider, data.prefix);
|
||||||
return !!addIconSet(storage, data);
|
return !!addIconSet(storage, data);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -404,11 +427,11 @@ coreModules.cache = storeCache;
|
|||||||
loadCache();
|
loadCache();
|
||||||
|
|
||||||
// Set API
|
// Set API
|
||||||
setAPIModule({
|
coreModules.api = API;
|
||||||
|
setDefaultAPIModule({
|
||||||
send: sendQuery,
|
send: sendQuery,
|
||||||
prepare: prepareQuery,
|
prepare: prepareQuery,
|
||||||
});
|
});
|
||||||
coreModules.api = API;
|
|
||||||
|
|
||||||
// Load observer
|
// Load observer
|
||||||
browserModules.observer = observer;
|
browserModules.observer = observer;
|
||||||
|
@ -84,9 +84,9 @@ function getGlobal(): JSONPRoot {
|
|||||||
/**
|
/**
|
||||||
* Calculate maximum icons list length for prefix
|
* Calculate maximum icons list length for prefix
|
||||||
*/
|
*/
|
||||||
function calculateMaxLength(prefix: string): number {
|
function calculateMaxLength(provider: string, prefix: string): number {
|
||||||
// Get config and store path
|
// Get config and store path
|
||||||
const config = getAPIConfig(prefix);
|
const config = getAPIConfig(provider);
|
||||||
if (!config) {
|
if (!config) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -112,7 +112,10 @@ function calculateMaxLength(prefix: string): number {
|
|||||||
config.maxURL -
|
config.maxURL -
|
||||||
maxHostLength -
|
maxHostLength -
|
||||||
config.path.length -
|
config.path.length -
|
||||||
endPoint.replace('{prefix}', prefix).replace('{icons}', '').length -
|
endPoint
|
||||||
|
.replace('{provider}', provider)
|
||||||
|
.replace('{prefix}', prefix)
|
||||||
|
.replace('{icons}', '').length -
|
||||||
extraLength;
|
extraLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,6 +129,7 @@ function calculateMaxLength(prefix: string): number {
|
|||||||
* Prepare params
|
* Prepare params
|
||||||
*/
|
*/
|
||||||
export const prepareQuery: IconifyAPIPrepareQuery = (
|
export const prepareQuery: IconifyAPIPrepareQuery = (
|
||||||
|
provider: string,
|
||||||
prefix: string,
|
prefix: string,
|
||||||
icons: string[]
|
icons: string[]
|
||||||
): APIQueryParams[] => {
|
): APIQueryParams[] => {
|
||||||
@ -134,11 +138,12 @@ export const prepareQuery: IconifyAPIPrepareQuery = (
|
|||||||
// Get maximum icons list length
|
// Get maximum icons list length
|
||||||
let maxLength = maxLengthCache[prefix];
|
let maxLength = maxLengthCache[prefix];
|
||||||
if (maxLength === void 0) {
|
if (maxLength === void 0) {
|
||||||
maxLength = calculateMaxLength(prefix);
|
maxLength = calculateMaxLength(provider, prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Split icons
|
// Split icons
|
||||||
let item: APIQueryParams = {
|
let item: APIQueryParams = {
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
icons: [],
|
icons: [],
|
||||||
};
|
};
|
||||||
@ -149,6 +154,7 @@ export const prepareQuery: IconifyAPIPrepareQuery = (
|
|||||||
// Next set
|
// Next set
|
||||||
results.push(item);
|
results.push(item);
|
||||||
item = {
|
item = {
|
||||||
|
provider,
|
||||||
prefix,
|
prefix,
|
||||||
icons: [],
|
icons: [],
|
||||||
};
|
};
|
||||||
@ -170,6 +176,7 @@ export const sendQuery: IconifyAPISendQuery = (
|
|||||||
params: APIQueryParams,
|
params: APIQueryParams,
|
||||||
status: RedundancyPendingItem
|
status: RedundancyPendingItem
|
||||||
): void => {
|
): void => {
|
||||||
|
const provider = params.provider;
|
||||||
const prefix = params.prefix;
|
const prefix = params.prefix;
|
||||||
const icons = params.icons;
|
const icons = params.icons;
|
||||||
const iconsList = icons.join(',');
|
const iconsList = icons.join(',');
|
||||||
@ -180,7 +187,9 @@ export const sendQuery: IconifyAPISendQuery = (
|
|||||||
const global = getGlobal();
|
const global = getGlobal();
|
||||||
|
|
||||||
// Callback hash
|
// Callback hash
|
||||||
let cbCounter = hash(host + ':' + prefix + ':' + iconsList);
|
let cbCounter = hash(
|
||||||
|
provider + ':' + host + ':' + prefix + ':' + iconsList
|
||||||
|
);
|
||||||
while (global[cbPrefix + cbCounter] !== void 0) {
|
while (global[cbPrefix + cbCounter] !== void 0) {
|
||||||
cbCounter++;
|
cbCounter++;
|
||||||
}
|
}
|
||||||
@ -189,6 +198,7 @@ export const sendQuery: IconifyAPISendQuery = (
|
|||||||
let path =
|
let path =
|
||||||
pathCache[prefix] +
|
pathCache[prefix] +
|
||||||
endPoint
|
endPoint
|
||||||
|
.replace('{provider}', provider)
|
||||||
.replace('{prefix}', prefix)
|
.replace('{prefix}', prefix)
|
||||||
.replace('{icons}', iconsList)
|
.replace('{icons}', iconsList)
|
||||||
.replace('{cb}', callbackName);
|
.replace('{cb}', callbackName);
|
||||||
|
@ -53,18 +53,20 @@ export function scanDOM(root?: HTMLElement): void {
|
|||||||
// Observer
|
// Observer
|
||||||
let paused = false;
|
let paused = false;
|
||||||
|
|
||||||
// List of icons to load
|
// List of icons to load: [provider][prefix][name] = boolean
|
||||||
const loadIcons: Record<string, Record<string, boolean>> = Object.create(
|
const loadIcons: Record<
|
||||||
null
|
string,
|
||||||
);
|
Record<string, Record<string, boolean>>
|
||||||
|
> = Object.create(null);
|
||||||
|
|
||||||
// Get root node and placeholders
|
// Get root node and placeholders
|
||||||
if (!root) {
|
if (!root) {
|
||||||
root = getRoot();
|
root = getRoot();
|
||||||
}
|
}
|
||||||
findPlaceholders(root).forEach(item => {
|
findPlaceholders(root).forEach((item) => {
|
||||||
const element = item.element;
|
const element = item.element;
|
||||||
const iconName = item.name;
|
const iconName = item.name;
|
||||||
|
const provider = iconName.provider;
|
||||||
const prefix = iconName.prefix;
|
const prefix = iconName.prefix;
|
||||||
const name = iconName.name;
|
const name = iconName.name;
|
||||||
let data: IconifyElementData = element[elementDataProperty];
|
let data: IconifyElementData = element[elementDataProperty];
|
||||||
@ -79,7 +81,7 @@ export function scanDOM(root?: HTMLElement): void {
|
|||||||
case 'loading':
|
case 'loading':
|
||||||
if (
|
if (
|
||||||
coreModules.api &&
|
coreModules.api &&
|
||||||
coreModules.api.isPending(prefix, name)
|
coreModules.api.isPending({ provider, prefix, name })
|
||||||
) {
|
) {
|
||||||
// Pending
|
// Pending
|
||||||
return;
|
return;
|
||||||
@ -88,7 +90,7 @@ export function scanDOM(root?: HTMLElement): void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check icon
|
// Check icon
|
||||||
const storage = getStorage(prefix);
|
const storage = getStorage(provider, prefix);
|
||||||
if (storage.icons[name] !== void 0) {
|
if (storage.icons[name] !== void 0) {
|
||||||
// Icon exists - replace placeholder
|
// Icon exists - replace placeholder
|
||||||
if (browserModules.observer && !paused) {
|
if (browserModules.observer && !paused) {
|
||||||
@ -124,12 +126,16 @@ export function scanDOM(root?: HTMLElement): void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (coreModules.api) {
|
if (coreModules.api) {
|
||||||
if (!coreModules.api.isPending(prefix, name)) {
|
if (!coreModules.api.isPending({ provider, prefix, name })) {
|
||||||
// Add icon to loading queue
|
// Add icon to loading queue
|
||||||
if (loadIcons[prefix] === void 0) {
|
if (loadIcons[provider] === void 0) {
|
||||||
loadIcons[prefix] = Object.create(null);
|
loadIcons[provider] = Object.create(null);
|
||||||
}
|
}
|
||||||
loadIcons[prefix][name] = true;
|
const providerLoadIcons = loadIcons[provider];
|
||||||
|
if (providerLoadIcons[prefix] === void 0) {
|
||||||
|
providerLoadIcons[prefix] = Object.create(null);
|
||||||
|
}
|
||||||
|
providerLoadIcons[prefix][name] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,17 +151,21 @@ export function scanDOM(root?: HTMLElement): void {
|
|||||||
// Load icons
|
// Load icons
|
||||||
if (coreModules.api) {
|
if (coreModules.api) {
|
||||||
const api = coreModules.api;
|
const api = coreModules.api;
|
||||||
Object.keys(loadIcons).forEach(prefix => {
|
Object.keys(loadIcons).forEach((provider) => {
|
||||||
api.loadIcons(
|
const providerLoadIcons = loadIcons[provider];
|
||||||
Object.keys(loadIcons[prefix]).map(name => {
|
Object.keys(providerLoadIcons).forEach((prefix) => {
|
||||||
const icon: IconifyIconName = {
|
api.loadIcons(
|
||||||
prefix,
|
Object.keys(providerLoadIcons[prefix]).map((name) => {
|
||||||
name,
|
const icon: IconifyIconName = {
|
||||||
};
|
provider,
|
||||||
return icon;
|
prefix,
|
||||||
}),
|
name,
|
||||||
checkPendingIcons
|
};
|
||||||
);
|
return icon;
|
||||||
|
}),
|
||||||
|
checkPendingIcons
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user