mirror of https://github.com/iconify/api.git
feat: filter icons by stroke and fill
This commit is contained in:
parent
d542004aab
commit
836b75ce79
|
|
@ -51,6 +51,10 @@ export const appConfig: AppConfig = {
|
|||
// Requires `enableIconLists` to be enabled
|
||||
// Disable this option if you do not need search functionality
|
||||
enableSearchEngine: true,
|
||||
|
||||
// Enables filtering icons by style: 'fill' or 'stroke'
|
||||
// Works only if search engine is enabled
|
||||
allowFilterIconsByStyle: true,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,7 +1,13 @@
|
|||
import type { IconifyAliases, IconifyJSON, IconifyOptional } from '@iconify/types';
|
||||
import { defaultIconProps } from '@iconify/utils/lib/icon/defaults';
|
||||
import { appConfig } from '../../../config/app';
|
||||
import type { IconSetIconNames, IconSetIconsListIcons, IconSetIconsListTag } from '../../../types/icon-set/extra';
|
||||
import type {
|
||||
IconSetIconNames,
|
||||
IconSetIconsListIcons,
|
||||
IconSetIconsListTag,
|
||||
IconStyle,
|
||||
} from '../../../types/icon-set/extra';
|
||||
import { getIconStyle } from './style';
|
||||
|
||||
const customisableProps = Object.keys(defaultIconProps) as (keyof IconifyOptional)[];
|
||||
|
||||
|
|
@ -43,6 +49,12 @@ export function generateIconSetIconsTree(iconSet: IconifyJSON): IconSetIconsList
|
|||
}
|
||||
|
||||
// Parse all icons
|
||||
let detectedIconStyle: IconStyle | undefined | null;
|
||||
const iconsWithStroke: Set<IconSetIconNames> = new Set();
|
||||
const iconsWithFill: Set<IconSetIconNames> = new Set();
|
||||
const checkIconStyle =
|
||||
appConfig.allowFilterIconsByStyle && appConfig.enableSearchEngine && appConfig.enableIconLists;
|
||||
|
||||
for (const name in iconSetIcons) {
|
||||
const isVisible = !iconSetIcons[name].hidden;
|
||||
const icon: IconSetIconNames = [name];
|
||||
|
|
@ -65,6 +77,22 @@ export function generateIconSetIconsTree(iconSet: IconifyJSON): IconSetIconsList
|
|||
uncategorised.push(icon);
|
||||
}
|
||||
}
|
||||
|
||||
// Check content
|
||||
if (checkIconStyle) {
|
||||
const body = iconSetIcons[name].body;
|
||||
const iconStyle = getIconStyle(body);
|
||||
if (iconStyle) {
|
||||
(iconStyle === 'stroke' ? iconsWithStroke : iconsWithFill).add(icon);
|
||||
}
|
||||
if (detectedIconStyle === void 0) {
|
||||
// First item
|
||||
detectedIconStyle = iconStyle;
|
||||
} else if (detectedIconStyle && detectedIconStyle !== iconStyle) {
|
||||
// Different style
|
||||
detectedIconStyle = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -145,6 +173,14 @@ export function generateIconSetIconsTree(iconSet: IconifyJSON): IconSetIconsList
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add style
|
||||
if (iconsWithFill.has(parentIcon)) {
|
||||
iconsWithFill.add(icon);
|
||||
}
|
||||
if (iconsWithStroke.has(parentIcon)) {
|
||||
iconsWithStroke.add(icon);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Treat as alias: add to parent icon
|
||||
|
|
@ -216,6 +252,22 @@ export function generateIconSetIconsTree(iconSet: IconifyJSON): IconSetIconsList
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Icon style
|
||||
if (checkIconStyle) {
|
||||
if (detectedIconStyle) {
|
||||
result.iconStyle = detectedIconStyle;
|
||||
} else if (iconsWithFill.size || iconsWithStroke.size) {
|
||||
// Mixed styles: assign to icon object
|
||||
result.iconStyle = 'mixed';
|
||||
iconsWithFill.forEach((item) => {
|
||||
item._is = 'fill';
|
||||
});
|
||||
iconsWithStroke.forEach((item) => {
|
||||
item._is = 'stroke';
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
import type { IconStyle } from '../../../types/icon-set/extra';
|
||||
|
||||
function getValues(body: string, prop: string): string[] {
|
||||
const chunks = body.split(prop + '="');
|
||||
chunks.shift();
|
||||
return chunks.map((item) => {
|
||||
const index = item.indexOf('"');
|
||||
return index > 0 ? item.slice(0, index) : '';
|
||||
});
|
||||
}
|
||||
|
||||
function hasValues(body: string, prop: string): boolean {
|
||||
const fills = getValues(body, prop);
|
||||
for (let i = 0; i < fills.length; i++) {
|
||||
switch (fills[i].toLowerCase()) {
|
||||
case '':
|
||||
case 'none':
|
||||
case 'transparent':
|
||||
case 'inherit':
|
||||
break;
|
||||
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if icon uses fill or stroke
|
||||
*
|
||||
* Returns null on failure
|
||||
*/
|
||||
export function getIconStyle(body: string): IconStyle | null {
|
||||
const hasStroke = hasValues(body, 'stroke');
|
||||
const hasFill = hasValues(body, 'fill');
|
||||
return hasStroke ? (hasFill ? null : 'stroke') : hasFill ? 'fill' : null;
|
||||
}
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
import { appConfig } from '../../config/app';
|
||||
import type { IconSetIconNames } from '../../types/icon-set/extra';
|
||||
import type { IconSetEntry } from '../../types/importers';
|
||||
import type { SearchIndexData, SearchKeywordsEntry, SearchParams, SearchResultsData } from '../../types/search';
|
||||
|
|
@ -19,6 +20,13 @@ export function search(
|
|||
return;
|
||||
}
|
||||
|
||||
// Merge params
|
||||
const fullParams = {
|
||||
...params,
|
||||
// Params extracted from query override default params
|
||||
...keywords.params,
|
||||
};
|
||||
|
||||
// Make sure all keywords exist
|
||||
keywords.searches = keywords.searches.filter((search) => {
|
||||
for (let i = 0; i < search.keywords.length; i++) {
|
||||
|
|
@ -54,15 +62,10 @@ export function search(
|
|||
}
|
||||
|
||||
// Get prefixes
|
||||
const basePrefixes = filterSearchPrefixes(data, iconSets, {
|
||||
...params,
|
||||
// Params extracted from query override default params
|
||||
...keywords.params,
|
||||
});
|
||||
const basePrefixes = filterSearchPrefixes(data, iconSets, fullParams);
|
||||
|
||||
// Prepare variables
|
||||
const addedIcons = Object.create(null) as Record<string, Set<IconSetIconNames>>;
|
||||
const foundPrefixes: Set<string> = new Set();
|
||||
const results: string[] = [];
|
||||
const limit = params.limit;
|
||||
|
||||
|
|
@ -147,6 +150,20 @@ export function search(
|
|||
continue;
|
||||
}
|
||||
|
||||
// Check style
|
||||
if (
|
||||
// Style is set
|
||||
fullParams.style &&
|
||||
// Enabled in config
|
||||
appConfig.allowFilterIconsByStyle &&
|
||||
// Icon set has mixed style (so it is assigned to icons) -> check icon
|
||||
iconSetIcons.iconStyle === 'mixed' &&
|
||||
item._is !== fullParams.style
|
||||
) {
|
||||
// Different icon style
|
||||
continue;
|
||||
}
|
||||
|
||||
// Find icon name that matches all keywords
|
||||
const name = item.find((name) => {
|
||||
for (let i = 0; i < testMatches.length; i++) {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { appConfig } from '../../config/app';
|
||||
import type { IconSetEntry } from '../../types/importers';
|
||||
import type { SearchIndexData, SearchParams } from '../../types/search';
|
||||
|
||||
|
|
@ -36,11 +37,6 @@ export function filterSearchPrefixes(
|
|||
): Readonly<string[]> {
|
||||
let prefixes: string[] | undefined;
|
||||
|
||||
// Filter by prefix
|
||||
if (params.prefixes) {
|
||||
prefixes = filterSearchPrefixesList(prefixes || data.sortedPrefixes, params.prefixes);
|
||||
}
|
||||
|
||||
// Filter by palette
|
||||
const palette = params.palette;
|
||||
if (typeof palette === 'boolean') {
|
||||
|
|
@ -50,6 +46,22 @@ export function filterSearchPrefixes(
|
|||
});
|
||||
}
|
||||
|
||||
// Filter by style
|
||||
if (appConfig.allowFilterIconsByStyle) {
|
||||
const style = params.style;
|
||||
if (style) {
|
||||
prefixes = (prefixes || data.sortedPrefixes).filter((prefix) => {
|
||||
const iconSetStyle = iconSets[prefix].item.icons.iconStyle;
|
||||
return iconSetStyle === style || iconSetStyle === 'mixed';
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Filter by prefix
|
||||
if (params.prefixes) {
|
||||
prefixes = filterSearchPrefixesList(prefixes || data.sortedPrefixes, params.prefixes);
|
||||
}
|
||||
|
||||
// TODO: add more filter options
|
||||
|
||||
return prefixes || data.sortedPrefixes;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { matchIconName } from '@iconify/utils/lib/icon/name';
|
||||
import { paramToBoolean } from '../../misc/bool';
|
||||
import type { IconStyle } from '../../types/icon-set/extra';
|
||||
import type { SearchKeywords, SearchKeywordsEntry } from '../../types/search';
|
||||
import { minPartialKeywordLength } from './partial';
|
||||
|
||||
|
|
@ -224,6 +225,7 @@ function addPartialPrefix(prefix: string, set: Set<string>): boolean {
|
|||
export function splitKeyword(keyword: string, allowPartial = true): SearchKeywords | undefined {
|
||||
const commonPrefixes: Set<string> = new Set();
|
||||
let palette: boolean | undefined;
|
||||
let iconStyle: IconStyle | undefined;
|
||||
|
||||
// Split by space, check for prefixes and reserved keywords
|
||||
const keywordChunks = keyword.toLowerCase().trim().split(/\s+/);
|
||||
|
|
@ -243,9 +245,32 @@ export function splitKeyword(keyword: string, allowPartial = true): SearchKeywor
|
|||
if (prefixChunks.length === 2) {
|
||||
const keyword = prefixChunks[0];
|
||||
const value = prefixChunks[1];
|
||||
let isKeyword = false;
|
||||
switch (keyword) {
|
||||
case 'palette': {
|
||||
palette = paramToBoolean(value);
|
||||
if (typeof palette === 'boolean') {
|
||||
isKeyword = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// style:fill, style:stroke
|
||||
case 'style': {
|
||||
if (value === 'fill' || value === 'stroke') {
|
||||
iconStyle = value;
|
||||
isKeyword = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// fill:true, stroke:true
|
||||
case 'fill':
|
||||
case 'stroke': {
|
||||
if (paramToBoolean(value)) {
|
||||
iconStyle = keyword;
|
||||
isKeyword = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -270,10 +295,13 @@ export function splitKeyword(keyword: string, allowPartial = true): SearchKeywor
|
|||
// All prefixes are bad: invalidate search query
|
||||
return;
|
||||
}
|
||||
|
||||
isKeyword = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
default: {
|
||||
if (!isKeyword) {
|
||||
// Icon with prefix
|
||||
if (hasPrefixes) {
|
||||
// Already had entry with prefix: invalidate query
|
||||
|
|
@ -303,7 +331,6 @@ export function splitKeyword(keyword: string, allowPartial = true): SearchKeywor
|
|||
keywords.push(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -316,8 +343,9 @@ export function splitKeyword(keyword: string, allowPartial = true): SearchKeywor
|
|||
}
|
||||
|
||||
if (paramChunks.length === 2) {
|
||||
const keyword = paramChunks[0];
|
||||
const value = paramChunks[1] as string;
|
||||
switch (paramChunks[0]) {
|
||||
switch (keyword) {
|
||||
// 'palette=true', 'palette=false' -> filter icon sets by palette
|
||||
case 'palette':
|
||||
palette = paramToBoolean(value);
|
||||
|
|
@ -326,6 +354,28 @@ export function splitKeyword(keyword: string, allowPartial = true): SearchKeywor
|
|||
}
|
||||
break;
|
||||
|
||||
// style=fill, style=stroke
|
||||
case 'style': {
|
||||
if (value === 'fill' || value === 'stroke') {
|
||||
iconStyle = value;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// fill=true, stroke=true
|
||||
// accepts only true as value
|
||||
case 'fill':
|
||||
case 'stroke': {
|
||||
if (paramToBoolean(value)) {
|
||||
iconStyle = keyword;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// 'prefix=material-symbols', 'prefix=material-'
|
||||
// 'prefixes=material-symbols,material-'
|
||||
case 'prefix':
|
||||
|
|
@ -390,6 +440,9 @@ export function splitKeyword(keyword: string, allowPartial = true): SearchKeywor
|
|||
if (typeof palette === 'boolean') {
|
||||
params.palette = palette;
|
||||
}
|
||||
if (iconStyle) {
|
||||
params.style = iconStyle;
|
||||
}
|
||||
return {
|
||||
searches,
|
||||
params,
|
||||
|
|
|
|||
|
|
@ -41,4 +41,8 @@ export interface AppConfig {
|
|||
// Requires `enableIconLists` to be enabled
|
||||
// Disable this option if you do not need search functionality
|
||||
enableSearchEngine: boolean;
|
||||
|
||||
// Enables filtering icons by style: 'fill' or 'stroke'
|
||||
// Works only if search engine is enabled
|
||||
allowFilterIconsByStyle: boolean;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,21 @@
|
|||
import type { IconifyInfo } from '@iconify/types';
|
||||
|
||||
/**
|
||||
* Icon style
|
||||
*/
|
||||
export type IconStyle = 'fill' | 'stroke';
|
||||
|
||||
/**
|
||||
* Extra props added to icons
|
||||
*/
|
||||
export interface ExtraIconSetIconNamesProps {
|
||||
_is?: IconStyle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Icon. First entry is main name, other entries are aliases
|
||||
*/
|
||||
export type IconSetIconNames = [string, ...string[]];
|
||||
export type IconSetIconNames = [string, ...string[]] & ExtraIconSetIconNamesProps;
|
||||
|
||||
/**
|
||||
* Tag
|
||||
|
|
@ -41,6 +53,9 @@ export interface IconSetIconsListIcons {
|
|||
|
||||
// Keywords, set if search engine is enabled
|
||||
keywords?: Record<string, Set<IconSetIconNames>>;
|
||||
|
||||
// Extra info
|
||||
iconStyle?: IconStyle | 'mixed';
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import type { IconStyle } from './icon-set/extra';
|
||||
|
||||
/**
|
||||
* List of keywords that can be used to autocomplete keyword
|
||||
*/
|
||||
|
|
@ -39,6 +41,9 @@ export interface SearchParams {
|
|||
// Filter icon sets by palette
|
||||
palette?: boolean;
|
||||
|
||||
// Filter icons by style
|
||||
style?: IconStyle;
|
||||
|
||||
// Keyword
|
||||
keyword: string;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,76 @@
|
|||
import { getIconStyle } from '../../lib/data/icon-set/lists/style';
|
||||
|
||||
describe('Checking icon style', () => {
|
||||
test('Fill', () => {
|
||||
expect(
|
||||
getIconStyle(
|
||||
'<path fill="currentColor" d="M244.377 427.349c0 6.85-.044 13.703-.044 20.597c60.027.09 120.053 0 180.077.046c0-6.853-.043-13.703-.043-20.554c-12.067-2.432-26.964-5.835-31.605-18.962c-46.101-114.703-92.869-229.187-138.352-344.11c-33.24-.575-66.479-.354-99.719-.132c6.188 13.88 11.36 28.2 17.77 41.99c-38.942 101.178-78.502 202.178-118.02 303.136c-4.464 12.862-19.096 15.737-30.808 18.167c0 6.763-.043 13.57-.043 20.378c38.278.177 76.556.044 114.835.088c-.044-6.939-.044-13.835-.087-20.73c-12.023-1.856-25.814-1.635-35.583-9.946c-7.69-7.425-4.287-19.007-1.105-27.715c7.647-19.757 14.897-39.693 23.25-59.186c46.37.266 92.69-.043 139.059.132c6.366 15.824 12.73 31.692 19.096 47.56c4.244 10.696 8.09 22.676 4.64 34.168c-8.93 14.81-28.289 13.927-43.318 15.074zM138.735 293.64c17.77-47.208 36.599-94.061 54.014-141.401c18.787 47.163 37.704 94.282 56.534 141.401a11615.148 11615.148 0 0 1-110.548 0z"/>'
|
||||
)
|
||||
).toBe('fill');
|
||||
expect(
|
||||
getIconStyle(
|
||||
'<g fill="currentColor" fill-rule="evenodd" stroke-width=".133"><path d="M64 256v192h384V64H64Zm375.742 0v183.742H72.258V72.258h367.484Z"/><path d="M326.606 277.232c-2.89 9.083-4.748 11.56-10.735 14.451c-5.368 2.684-7.226 4.749-7.226 8.671c0 4.336 1.032 5.161 5.987 5.161h5.987l.826 33.446c.62 27.664 1.239 34.89 4.336 40.464c5.987 10.942 21.47 15.277 40.464 11.561c5.78-1.238 6.4-2.064 6.4-9.083v-7.846l-11.561.413c-16.723.413-17.342-1.032-17.342-38.4v-30.555h28.903V289h-28.903v-22.71h-6.813c-6.4 0-7.02.619-10.323 10.942zm-149.058 12.18c-3.303 1.239-8.67 4.542-11.767 7.432c-5.987 5.575-5.575 5.781-8.878-4.748c-.62-2.064-3.716-3.097-9.29-3.097h-8.258v101.162h22.71v-32.826c0-18.168.825-35.303 1.858-37.987c3.716-9.29 10.322-13.833 21.058-13.833c8.051 0 10.529 1.033 14.038 5.368c3.923 5.161 4.336 8.258 4.336 42.323v36.955h22.709v-34.065c0-44.8 2.684-50.58 23.536-50.58c7.432 0 9.91 1.032 13.42 5.367c3.922 5.161 4.335 8.258 4.335 42.323v36.955h23.122l-.825-39.846c-.826-43.974-2.89-52.438-14.246-58.425c-15.07-7.64-36.335-5.162-47.07 5.367l-5.988 6.194l-3.922-5.161c-6.813-9.497-26.839-13.833-40.878-8.878zM326.606 130.65c-2.89 9.085-4.748 11.562-10.735 14.453c-5.368 2.683-7.226 4.748-7.226 8.67c0 4.336 1.032 5.162 5.987 5.162h5.987l.826 33.445c.62 27.664 1.239 34.89 4.336 40.464c5.987 10.942 21.47 15.278 40.464 11.562c5.78-1.239 6.4-2.065 6.4-9.084v-7.845l-11.561.413c-16.723.413-17.342-1.033-17.342-38.4v-30.555h28.903v-16.516h-28.903v-22.71h-6.813c-6.4 0-7.02.62-10.323 10.942zm-149.058 12.182c-3.303 1.238-8.67 4.541-11.767 7.432c-5.987 5.574-5.575 5.78-8.878-4.749c-.62-2.064-3.716-3.096-9.29-3.096h-8.258v101.16h22.71v-32.825c0-18.168.825-35.303 1.858-37.987c3.716-9.29 10.322-13.832 21.058-13.832c8.051 0 10.529 1.032 14.038 5.368c3.923 5.16 4.336 8.258 4.336 42.322v36.955h22.709v-34.065c0-44.8 2.684-50.58 23.536-50.58c7.432 0 9.91 1.032 13.42 5.368c3.922 5.16 4.335 8.258 4.335 42.322v36.955h23.122l-.825-39.845c-.826-43.974-2.89-52.439-14.246-58.426c-15.07-7.639-36.335-5.161-47.07 5.368l-5.988 6.193l-3.922-5.161c-6.813-9.497-26.839-13.832-40.878-8.877z"/></g>'
|
||||
)
|
||||
).toBe('fill');
|
||||
expect(
|
||||
getIconStyle(
|
||||
'<path fill="currentColor" fill-rule="evenodd" d="M10 2a1 1 0 0 0-1.79-.614l-7 9a1 1 0 0 0 0 1.228l7 9A1 1 0 0 0 10 20v-3.99c5.379.112 7.963 1.133 9.261 2.243c1.234 1.055 1.46 2.296 1.695 3.596l.061.335a1 1 0 0 0 1.981-.122c.171-2.748-.086-6.73-2.027-10.061C19.087 8.768 15.694 6.282 10 6.022V2Z" clip-rule="evenodd"/>'
|
||||
)
|
||||
).toBe('fill');
|
||||
expect(
|
||||
getIconStyle(
|
||||
'<mask id="svgIDa"><circle cx="256" cy="256" r="256" fill="#fff"/></mask><g mask="url(#svgIDa)"><path fill="#0052b4" d="M256 0h256v512H0V256Z"/><path fill="#eee" d="M0 0v32l32 32L0 96v160h32l32-32l32 32h32v-83l83 83h45l-8-16l8-15v-14l-83-83h83V96l-32-32l32-32V0H96L64 32L32 0Z"/><path fill="#d80027" d="M32 0v32H0v64h32v160h64V96h160V32H96V0Zm96 128l128 128v-31l-97-97z"/><path fill="#6da544" d="m320 144l48-80l48 80z"/><circle cx="368" cy="144" r="48" fill="#acabb1"/><path fill="#338af3" d="M320 144v77c0 36 48 48 48 48s48-12 48-48v-77z"/><rect width="32" height="128" x="288" y="128" fill="#ff9811" rx="16" ry="16"/><rect width="32" height="128" x="416" y="128" fill="#ff9811" rx="16" ry="16"/><path fill="#6da544" d="m368 160l-48 67c2 11 9 19 16 26l32-45l32 45c8-7 14-15 16-26z"/></g>'
|
||||
)
|
||||
).toBe('fill');
|
||||
expect(
|
||||
getIconStyle(
|
||||
'<path fill="currentColor" fill-opacity=".3" d="M17 5.33C17 4.6 16.4 4 15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33V15h10V5.33z"/><path fill="currentColor" d="M7 15v5.67C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V15H7z"/>'
|
||||
)
|
||||
).toBe('fill');
|
||||
});
|
||||
|
||||
test('Stroke', () => {
|
||||
expect(
|
||||
getIconStyle(
|
||||
'<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 8h7a3 3 0 1 0-3-3M4 16h11a3 3 0 1 1-3 3M2 12h17a3 3 0 1 0-3-3"/>'
|
||||
)
|
||||
).toBe('stroke');
|
||||
expect(
|
||||
getIconStyle(
|
||||
'<circle cx="23.573" cy="14.408" r="9.309" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/><circle cx="23.573" cy="14.251" r="4.515" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="m21.344 23.789l-.072 14.045c-4.271-.972-7.874-2.772-9.793-6.66L14.17 28.5l-9.67.018l.071 9.511l2.87-2.78C11.12 40.62 16.78 42.957 24 42.899m2.763-19.606l-.036 14.54c4.272-.971 7.875-2.771 9.794-6.659L33.83 28.5l9.67.018l-.071 9.511l-2.87-2.78C36.88 40.62 31.22 42.957 24 42.899"/>'
|
||||
)
|
||||
).toBe('stroke');
|
||||
expect(
|
||||
getIconStyle(
|
||||
'<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16m-10 6h10M6 18h14"/>'
|
||||
)
|
||||
).toBe('stroke');
|
||||
});
|
||||
|
||||
test('Mixed / none', () => {
|
||||
expect(getIconStyle('<g />')).toBeNull();
|
||||
expect(getIconStyle('<path fill="none" d="" />')).toBeNull();
|
||||
expect(getIconStyle('<path fill="" d="" />')).toBeNull();
|
||||
expect(getIconStyle('<path fill="currentColor fill="" />')).toBeNull();
|
||||
expect(
|
||||
getIconStyle(
|
||||
'<path fill="currentColor" d="M212.277 418v382.37h1574.785V418z"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="70" d="M213.105 1000V418h1573.79v1164H600V791.606V1582H213.105v-401.564h1573.79h-1573.79z"/>'
|
||||
)
|
||||
).toBeNull();
|
||||
expect(
|
||||
getIconStyle(
|
||||
'<path fill="#e6e7e8" d="M63.6 56.737a6.856 6.856 0 0 1-6.854 6.86H6.857c-3.784.001-6.853-3.071-6.853-6.86V6.856A6.856 6.856 0 0 1 6.857 0h49.889A6.855 6.855 0 0 1 63.6 6.856v49.881"/><path fill="none" stroke="#005" stroke-linecap="round" stroke-opacity=".221" stroke-width=".4" d="M9.429 4.424v55.15zm6.451 0v55.15zm6.451 0v55.15zm6.451 0v55.15zm6.448 0v55.15zm6.454 0v55.15zm6.446 0v55.15zm6.46 0v55.15zM4.185 54.775h55.15zm0-6.455h55.15zm0-6.447h55.15zm0-6.451h55.15z"/><path fill="#f05a28" d="M36.725 63.65V36.99c0-2.06-2.669-3.62-4.728-3.62c-2.059 0-4.729 1.561-4.729 3.62v26.66h9.457"/><path fill="#d04427" d="M33.778 33.718c-.594-.217-1.211-.348-1.781-.348c-2.059 0-4.729 1.561-4.729 3.62v26.66h3.565V36.99c0-1.488 1.397-2.706 2.945-3.272"/><path fill="none" stroke="#005" stroke-linecap="round" stroke-opacity=".221" stroke-width=".4" d="M4.185 28.971h55.15zm0-6.451h55.15z"/><path fill="#208d55" d="M19.11 63.65V24.988c0-2.059-3.668-3.727-5.728-3.727c-2.059 0-5.729 1.668-5.729 3.727V63.65H19.11"/><path fill="#1b8049" d="M15.551 21.789c-.771-.27-1.542-.438-2.163-.438c-2.059 0-5.729 1.668-5.729 3.727V63.74h4.325V25.078c0-1.438 1.788-2.668 3.567-3.289"/><path fill="none" stroke="#005" stroke-linecap="round" stroke-opacity=".221" stroke-width=".4" d="M4.185 16.07h55.15zm0-6.451h55.15z"/><path fill="#0867a3" d="M55.942 63.65V6.985c0-2.059-3.669-3.727-5.728-3.727c-2.059 0-5.729 1.668-5.729 3.727V63.65h11.457"/><path fill="#055e8c" d="M52.35 3.684c-.762-.262-1.52-.426-2.135-.426c-2.059 0-5.729 1.668-5.729 3.727V63.65h4.271V6.985c0-1.443 1.804-2.682 3.593-3.301"/>'
|
||||
)
|
||||
).toBeNull();
|
||||
expect(
|
||||
getIconStyle(
|
||||
'<path fill="#c7e755" d="M59.5 30.6C59.5 54.1 32 62 32 62S4.5 54.1 4.5 30.6C4.5 13.1 15.5 2 32 2s27.5 11.1 27.5 28.6z"/><g fill="#454749"><path d="M23.4 26.4c4 3.8 5.1 8.9 2.6 11.4c-2.5 2.4-7.8 1.3-11.7-2.5c-4-3.8-5.1-8.9-2.6-11.4c2.5-2.5 7.7-1.4 11.7 2.5"/><path d="M26.4 30.6c-2.6-2.3-5.2-4.1-8-5.7c-1.4-.8-2.9-1.5-4.4-2.1c-1.5-.6-3.1-1.2-4.7-1.8c1.7-.2 3.5-.1 5.2.3c1.7.4 3.4 1 4.9 1.8c1.5.8 2.9 1.9 4.2 3.2c1.1 1.2 2.2 2.6 2.8 4.3"/></g><path fill="#fff" d="M20.4 25c2 1.2 3.1 3.1 2.5 4.1c-.7 1-2.9.8-4.9-.4c-2-1.2-3.1-3.1-2.5-4.1c.7-1 2.8-.8 4.9.4"/><g fill="#454749"><path d="M40.6 26.4c-4 3.8-5.1 8.9-2.6 11.4c2.5 2.4 7.8 1.3 11.7-2.5c4-3.8 5.1-8.9 2.6-11.4c-2.5-2.5-7.7-1.4-11.7 2.5"/><path d="M37.6 30.6c.6-1.6 1.7-3 2.9-4.3c1.2-1.2 2.6-2.3 4.2-3.2c1.5-.9 3.2-1.5 4.9-1.8c1.7-.4 3.4-.5 5.2-.3c-1.6.6-3.2 1.1-4.7 1.8c-1.5.6-3 1.3-4.4 2.1c-2.9 1.5-5.5 3.4-8.1 5.7"/></g><path fill="#fff" d="M43.6 25c-2 1.2-3.1 3.1-2.5 4.1c.7 1 2.9.8 4.9-.4c2-1.2 3.1-3.1 2.5-4.1c-.7-1-2.8-.8-4.9.4"/><path fill="#454749" stroke="#454749" stroke-miterlimit="10" d="M32 48.6c-7.6 0-10.7-3.7-10.7-2.4c0 1.9 4.8 4.4 10.7 4.4s10.7-2.5 10.7-4.4c0-1.3-3.1 2.4-10.7 2.4z"/>'
|
||||
)
|
||||
).toBeNull();
|
||||
expect(
|
||||
getIconStyle(
|
||||
'<g fill="none" stroke="#000" stroke-linejoin="round" stroke-width="4"><path fill="#2F88FF" d="M44 44V20L24 4L4 20L4 44H16V26H32V44H44Z"/><path stroke-linecap="round" d="M24 44V34"/></g>'
|
||||
)
|
||||
).toBeNull();
|
||||
});
|
||||
});
|
||||
|
|
@ -160,5 +160,19 @@ describe('Creating search index, checking prefixes', () => {
|
|||
palette: true,
|
||||
})
|
||||
).toEqual([]);
|
||||
|
||||
// Style
|
||||
expect(
|
||||
filterSearchPrefixes(searchIndex, iconSets, {
|
||||
...baseParams,
|
||||
style: 'fill',
|
||||
})
|
||||
).toEqual(['mdi-light', 'mdi-test-prefix']);
|
||||
expect(
|
||||
filterSearchPrefixes(searchIndex, iconSets, {
|
||||
...baseParams,
|
||||
style: 'stroke',
|
||||
})
|
||||
).toEqual([]);
|
||||
}, 5000);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -97,5 +97,21 @@ describe('Searching icons', () => {
|
|||
],
|
||||
hasMore: false,
|
||||
});
|
||||
|
||||
// Search with style and palette
|
||||
expect(
|
||||
search(
|
||||
{
|
||||
keyword: 'bookmark style:fill palette:true',
|
||||
limit: 999,
|
||||
},
|
||||
searchIndex,
|
||||
iconSets
|
||||
)
|
||||
).toEqual({
|
||||
prefixes: ['emojione-v1'],
|
||||
names: ['emojione-v1:bookmark', 'emojione-v1:bookmark-tabs'],
|
||||
hasMore: false,
|
||||
});
|
||||
}, 5000);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -305,6 +305,54 @@ describe('Splitting keywords', () => {
|
|||
},
|
||||
});
|
||||
|
||||
expect(splitKeyword('home style:fill')).toEqual({
|
||||
searches: [
|
||||
{
|
||||
keywords: [],
|
||||
},
|
||||
],
|
||||
partial: 'home',
|
||||
params: {
|
||||
style: 'fill',
|
||||
},
|
||||
});
|
||||
|
||||
expect(splitKeyword('home style=stroke')).toEqual({
|
||||
searches: [
|
||||
{
|
||||
keywords: [],
|
||||
},
|
||||
],
|
||||
partial: 'home',
|
||||
params: {
|
||||
style: 'stroke',
|
||||
},
|
||||
});
|
||||
|
||||
expect(splitKeyword('home fill=true')).toEqual({
|
||||
searches: [
|
||||
{
|
||||
keywords: [],
|
||||
},
|
||||
],
|
||||
partial: 'home',
|
||||
params: {
|
||||
style: 'fill',
|
||||
},
|
||||
});
|
||||
|
||||
expect(splitKeyword('home stroke=true')).toEqual({
|
||||
searches: [
|
||||
{
|
||||
keywords: [],
|
||||
},
|
||||
],
|
||||
partial: 'home',
|
||||
params: {
|
||||
style: 'stroke',
|
||||
},
|
||||
});
|
||||
|
||||
// Too short for partial
|
||||
expect(splitKeyword('ab')).toEqual({
|
||||
searches: [
|
||||
|
|
|
|||
Loading…
Reference in New Issue