refactor(webapp): migrate icons (#9238)

This commit is contained in:
Ulf Gebhardt 2026-02-17 23:40:51 +01:00 committed by GitHub
parent 4c4763f62a
commit 77a1e0964b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
230 changed files with 2217 additions and 1275 deletions

View File

@ -81,10 +81,10 @@ Phase 0: ██████████ 100% (6/6 Aufgaben) ✅
Phase 1: ██████████ 100% (6/6 Aufgaben) ✅
Phase 2: ██████████ 100% (26/26 Aufgaben) ✅
Phase 3: ██████████ 100% (24/24 Aufgaben) ✅ - Webapp-Integration komplett
Phase 4: ██░░░░░░░░ 18% (3/17 Aufgaben) - OsButton ✅, OsIcon ✅, System-Icons ✅
Phase 4: ██░░░░░░░░ 24% (4/17 Aufgaben) - OsButton ✅, OsIcon ✅, System-Icons ✅, BaseIcon→OsIcon Migration ✅
Phase 5: ░░░░░░░░░░ 0% (0/7 Aufgaben)
───────────────────────────────────────
Gesamt: ████████░░ 76% (65/86 Aufgaben)
Gesamt: ████████░░ 77% (66/86 Aufgaben)
```
### Katalogisierung (Details in KATALOG.md)
@ -131,31 +131,53 @@ System-Icons:
└─ plus.svg (Plus/Add)
Ocelot-Icons (separates Entry-Point):
└─ angle-down.svg (Dropdown-Pfeil)
└─ 82 Icons (Feature-Icons + Kategorie-Icons aus Webapp migriert)
BaseIcon → OsIcon Webapp-Migration: ✅
├─ 131 <base-icon> in 70+ Dateien → <os-icon :icon="...">
├─ 82 SVGs in ocelot/icons/svgs/ (inkl. 17 Kategorie-Icons)
├─ vite-svg-icon Plugin erweitert (rect, circle, polygon, polyline, ellipse, line)
├─ Kategorie-Icons: DB-String → toCamelCase() → ocelotIcons Lookup
├─ Jest Mocks: @ocelot-social/ui/ocelot für ocelotIcons in Tests
├─ Tests aktualisiert: 911/939 Tests bestanden (3 pre-existing failures)
└─ 0 base-icon/BaseIcon Referenzen verbleibend
```
---
## Aktueller Stand
**Letzte Aktualisierung:** 2026-02-15 (Session 21)
**Letzte Aktualisierung:** 2026-02-15 (Session 22)
**Aktuelle Phase:** Phase 4 - OsIcon ✅ implementiert, System-Icons eingerichtet
**Aktuelle Phase:** Phase 4 - OsIcon ✅, BaseIcon → OsIcon Webapp-Migration ✅
**Zuletzt abgeschlossen (Session 21 - OsIcon Komponente, System-Icons, Ocelot-Umbenennung):**
**Zuletzt abgeschlossen (Session 22 - BaseIcon → OsIcon Webapp-Migration):**
- [x] 131 `<base-icon>` Nutzungen in 70+ Dateien → `<os-icon :icon="icons.xxx">` migriert
- [x] 82 Ocelot-Icons in `packages/ui/src/ocelot/icons/svgs/` (von 1 auf 82)
- [x] 17 Kategorie-Icons aus Webapp kopiert (networking, energy, psyche, movement, finance, child, mobility, shopping-cart, peace, politics, nature, science, health, media, spirituality, culture, miscellaneous)
- [x] vite-svg-icon Plugin erweitert: unterstützt `<rect>`, `<circle>`, `<polygon>`, `<polyline>`, `<ellipse>`, `<line>` (war path-only)
- [x] Alle neuen SVGs auf Single-Line minifiziert (Multiline brach JS-String-Literale)
- [x] Kategorie-Icons: DB-String → `toCamelCase()``ocelotIcons[key]` Lookup (Category/index.vue, CategoriesFilter.vue, CategoriesSelect.vue, admin/categories.vue)
- [x] `created() { this.icons = ocelotIcons }` Pattern in allen Komponenten (non-reactive)
- [x] MenuLegend.vue: `legendItems` von `data()``computed` (data() läuft vor created(), this.icons undefined)
- [x] HeaderMenu.vue: Map-Button Icon-Größe korrigiert (`size="xl"` + negative Margin)
- [x] ShowPassword.vue: `:data-test="iconName"` entfernt (Icon ist jetzt Render-Function, kein String)
- [x] Jest-Tests aktualisiert: OsIcon + ocelotIcons statt BaseIcon + String-Namen
- Category/index.spec.js, ProfileAvatar.spec.js, CounterIcon.spec.js, ReportRow.spec.js
- ActionButton.spec.js, ComponentSlider.spec.js, ShowPassword.spec.js, LoginForm.spec.js
- [x] 8 stale Snapshot-Dateien gelöscht
- [x] Jest Mock: `test/__mocks__/@ocelot-social/ui/ocelot.js` für ocelotIcons in Tests
- [x] CSS: `.base-icon``.os-icon` in main.scss und Category/index.vue
- [x] 0 `base-icon`/`BaseIcon` Referenzen verbleibend in gesamter Webapp
- [x] 911/939 Tests bestanden (3 pre-existing Jest worker crashes)
**Zuvor abgeschlossen (Session 21 - OsIcon Komponente, System-Icons, Ocelot-Umbenennung):**
- [x] OsIcon Komponente implementiert (name, icon, size Props; Vue 2/3 via vue-demi h())
- [x] System-Icons: check, close, plus (SVG, viewBox 0 0 32 32, stroke-basiert)
- [x] Custom vite-svg-icon Plugin: SVG → Vue Render-Function via `?icon` Query
- [x] Icon-Größen: xs(0.75em), sm(0.875em), md(1.2em), lg(1.5em), xl(2em), 2xl(2.5em)
- [x] A11y: decorative (aria-hidden, default) / semantic (role="img" + aria-label)
- [x] fill-current für Farbvererbung vom Parent
- [x] OsButton nutzt OsIcon statt inline SVG für Icon-Rendering
- [x] Ocelot-Icons: separates Entry-Point (ocelot.mjs) mit dynamischem Loading via import.meta.glob
- [x] `src/webapp/``src/ocelot/` umbenannt (konsistentes Naming)
- [x] check-completeness erweitert: unterstützt ocelot/ Verzeichnis
- [x] OsIcon: 211 Zeilen Unit-Tests, Visual Tests mit checkA11y(), Keyboard A11y
- [x] 100% Test-Coverage für OsIcon
- [x] OsButton Stories bereinigt (OsIcon statt Inline-SVGs)
**Zuvor abgeschlossen (Session 20 - `as`-Prop + nuxt-link Migration):**
- [x] OsButton: `as` Prop implementiert (polymorphe Komponente: `button`, `a`, `nuxt-link`, `router-link`, Custom-Komponenten)
@ -200,8 +222,7 @@ Ocelot-Icons (separates Entry-Point):
- [ ] OsSpinner Komponente (vereint DsSpinner + LoadingSpinner)
- [ ] OsCard Komponente (vereint DsCard + BaseCard)
- [ ] Weitere Tier 1 Komponenten
- [ ] BaseIcon → OsIcon Webapp-Migration (131 Nutzungen)
- [ ] Snapshots/Tests aktualisieren
- [ ] Browser-Fehler untersuchen: `TypeError: Cannot read properties of undefined (reading 'heartO')` (ocelotIcons undefined im Browser trotz korrekter Webpack-Aliase)
**Manuelle Setup-Aufgaben (außerhalb Code):**
- [ ] `NPM_TOKEN` als GitHub Secret einrichten (für npm publish in ui-release.yml)
@ -475,6 +496,7 @@ Jeder migrierte Button muss manuell geprüft werden: Normal, Hover, Focus, Activ
**Infrastruktur**
- [x] System-Icons einrichten ✅ vite-svg-icon Plugin, 3 System-Icons, Ocelot-Icons Entry-Point
- [x] BaseIcon → OsIcon Webapp-Migration ✅ 131 Nutzungen, 82 Ocelot-Icons, 0 BaseIcon verbleibend
- [ ] CI docs-check Workflow (JSDoc-Coverage, README-Aktualität)
### Phase 5: Finalisierung
@ -768,7 +790,7 @@ import { ocelotIcons } from '@ocelot-social/ui/ocelot'
| Styleguide (_all) | 616 | Nicht übernehmen (FontAwesome 4 komplett) |
| Webapp (svgs) | 238 | Feature-Icons, bleiben in Webapp |
| **Library (system)** | **3** | ✅ check, close, plus |
| **Ocelot-Icons** | **1** | ✅ angle-down (separates Entry-Point) |
| **Ocelot-Icons** | **82** | ✅ Feature-Icons + Kategorie-Icons (separates Entry-Point) |
---
@ -1543,6 +1565,18 @@ Bei der Migration werden:
| 2026-02-15 | **OsButton Stories** | Bereinigt: Inline-SVG-Komponenten durch OsIcon ersetzt; WithAriaLabel-Story entfernt; InheritColor-Story vereinfacht |
| 2026-02-15 | **check-completeness** | Erweitert für ocelot/ Verzeichnis; unterstützt OsIcon-Patterns |
| 2026-02-15 | **svg-icon.d.ts** | TypeScript-Deklaration für `?icon` Import-Query (Component-Typ) |
| 2026-02-15 | **BaseIcon → OsIcon Migration** | 131 `<base-icon>` in 70+ Dateien → `<os-icon :icon="icons.xxx">`, 0 BaseIcon verbleibend |
| 2026-02-15 | **82 Ocelot-Icons** | Von 1 auf 82 Icons: Feature-Icons + 17 Kategorie-Icons aus Webapp kopiert |
| 2026-02-15 | **vite-svg-icon erweitert** | Unterstützt jetzt `<rect>`, `<circle>`, `<polygon>`, `<polyline>`, `<ellipse>`, `<line>` (war path-only) |
| 2026-02-15 | **SVG-Minifizierung** | Alle 21 neuen SVGs auf Single-Line minifiziert (Multiline brach JS-String-Literale im Plugin) |
| 2026-02-15 | **Kategorie-Icons** | DB-String → `toCamelCase()``ocelotIcons[key]` Lookup in Category, CategoriesFilter, CategoriesSelect, admin/categories |
| 2026-02-15 | **MenuLegend.vue Fix** | `legendItems` von `data()``computed` (`data()` läuft vor `created()`, `this.icons` undefined) |
| 2026-02-15 | **HeaderMenu.vue Fix** | Map-Button Icon-Größe: `size="xl"` + negative Margin (OsIcon md=1.2em vs BaseIcon --large=2.2em) |
| 2026-02-15 | **ShowPassword.vue Fix** | `:data-test="iconName"` entfernt (Icon ist jetzt Render-Function statt String) |
| 2026-02-15 | **Test-Updates (8 Specs)** | Category, ProfileAvatar, CounterIcon, ReportRow, ActionButton, ComponentSlider, ShowPassword, LoginForm: BaseIcon → OsIcon + ocelotIcons |
| 2026-02-15 | **8 Snapshots gelöscht** | Stale Snapshot-Dateien entfernt nach BaseIcon → OsIcon Migration |
| 2026-02-15 | **CSS Migration** | `.base-icon``.os-icon` in main.scss und Category/index.vue |
| 2026-02-15 | **Jest Mock ocelot** | `test/__mocks__/@ocelot-social/ui/ocelot.js` für ocelotIcons in Jest-Umgebung |
---

View File

@ -144,21 +144,23 @@
"size-limit": [
{
"path": "dist/index.mjs",
"limit": "16 kB",
"limit": "15 kB",
"brotli": true
},
{
"path": "dist/tailwind.preset.mjs",
"limit": "2 kB"
"limit": "1 kB",
"brotli": true
},
{
"path": "dist/ocelot.mjs",
"limit": "5 kB",
"limit": "45 kB",
"brotli": true
},
{
"path": "dist/style.css",
"limit": "10 kB"
"limit": "5 kB",
"brotli": true
}
]
}

View File

@ -1,6 +1,6 @@
import { mount } from '@vue/test-utils'
import { describe, expect, it } from 'vitest'
import { defineComponent, h } from 'vue-demi'
import { defineComponent, h, markRaw } from 'vue-demi'
import OsButton from './OsButton.vue'
@ -570,16 +570,18 @@ describe('osButton', () => {
})
it('renders a component passed as as', () => {
const FakeLink = defineComponent({
props: { to: { type: String, default: undefined } },
setup(props, { slots }) {
return () => h('a', { href: props.to }, slots.default?.())
},
})
const FakeLink = markRaw(
defineComponent({
props: { to: { type: String, default: undefined } },
setup(props, { slots }) {
return () => h('a', { href: props.to }, slots.default?.())
},
}),
)
const wrapper = mount(OsButton, {
props: { as: FakeLink },
attrs: { to: '/groups' },
slots: { default: 'Groups' },
slots: { default: () => 'Groups' },
})
expect((wrapper.element as HTMLElement).tagName).toBe('A')

View File

@ -237,15 +237,15 @@
/* v8 ignore stop */
const { class: attrClass, ...restAttrs } = attrs as Record<string, unknown>
return h(
tag,
{
...buttonData,
class: cn(buttonClass, attrClass || ''),
...restAttrs,
},
children,
)
const nodeProps = {
...buttonData,
class: cn(buttonClass, attrClass || ''),
...restAttrs,
}
// Components expect slot functions; HTML elements accept VNode arrays
return typeof tag === 'string'
? h(tag, nodeProps, children)
: h(tag, nodeProps, { default: () => children })
}
},
})

View File

@ -62,7 +62,7 @@ export const Playground: StoryObj<PlaygroundArgs> = {
}),
}
export const AllSystemIcons: Story = {
export const AllIcons: Story = {
render: () => ({
components: { OsIcon },
setup() {

View File

@ -32,7 +32,7 @@ async function checkA11y(page: Page) {
test.describe('OsIcon keyboard accessibility', () => {
test('decorative icons are not focusable', async ({ page }) => {
await page.goto(`${STORY_URL}--all-system-icons&viewMode=story`)
await page.goto(`${STORY_URL}--all-icons&viewMode=story`)
const root = page.locator(STORY_ROOT)
await root.waitFor()
@ -50,13 +50,13 @@ test.describe('OsIcon keyboard accessibility', () => {
})
test.describe('OsIcon visual regression', () => {
test('all system icons', async ({ page }) => {
await page.goto(`${STORY_URL}--all-system-icons&viewMode=story`)
test('all icons', async ({ page }) => {
await page.goto(`${STORY_URL}--all-icons&viewMode=story`)
const root = page.locator(STORY_ROOT)
await root.waitFor()
await waitForFonts(page)
await expect(root.locator('.grid')).toHaveScreenshot('all-system-icons.png')
await expect(root.locator('.grid')).toHaveScreenshot('all-icons.png')
await checkA11y(page)
})

View File

@ -49,12 +49,19 @@
const sizeClass = ICON_SIZES[props.size]
// Vue 2's h() cannot handle plain arrow functions as components (only
// constructor functions or option objects). SYSTEM_ICONS entries are
// arrow functions that return VNodes, so call them directly.
// constructor functions or option objects). Icon render functions are
// arrow functions that accept optional (h, isVue2) and return VNodes.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const isRenderFn = typeof iconComponent === 'function' && !(iconComponent as any).cid
// In Vue 2, pass $createElement (bound to this instance) so icons avoid
// the globally-imported h() which requires currentInstance in Vue 2.7.
const createElement = /* v8 ignore next -- Vue 2 only */ isVue2
? // eslint-disable-next-line @typescript-eslint/no-explicit-any
(instance?.proxy as any)?.$createElement
: h
const iconVNode = isRenderFn
? (iconComponent as () => ReturnType<typeof h>)()
? (iconComponent as (...args: unknown[]) => ReturnType<typeof h>)(createElement, isVue2)
: h(iconComponent)
/* v8 ignore start -- Vue 2 branch tested in webapp Jest tests */
@ -75,7 +82,7 @@
{
class: [
cn(
'os-icon inline-flex items-center shrink-0',
'os-icon inline-flex items-center align-bottom shrink-0',
sizeClass,
'[&>svg]:h-full [&>svg]:w-auto [&>svg]:fill-current',
),
@ -103,7 +110,7 @@
'span',
{
class: cn(
'os-icon inline-flex items-center shrink-0',
'os-icon inline-flex items-center align-bottom shrink-0',
sizeClass,
'[&>svg]:h-full [&>svg]:w-auto [&>svg]:fill-current',
attrClass as ClassValue,

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -1,4 +1,4 @@
import { OsIcon, SYSTEM_ICONS } from '#src/components/OsIcon'
import { OsIcon } from '#src/components/OsIcon'
import { ocelotIcons } from './index'
@ -11,33 +11,20 @@ const meta: Meta = {
export default meta
const systemEntries = Object.entries(SYSTEM_ICONS)
const ocelotEntries = Object.entries(ocelotIcons)
const allEntries = Object.entries(ocelotIcons)
export const AllIcons: StoryObj = {
render: () => ({
components: { OsIcon },
setup() {
return { systemEntries, ocelotEntries }
return { allEntries }
},
template: `
<div data-testid="icon-gallery" class="flex flex-col gap-6">
<div>
<h3 class="text-sm font-bold mb-2">Library Icons</h3>
<div class="grid grid-cols-5 gap-4">
<div v-for="[name, icon] in systemEntries" :key="name" class="flex flex-col items-center gap-2 p-3 rounded border border-gray-200">
<OsIcon :icon="icon" size="xl" />
<span class="text-xs text-gray-600">{{ name }}</span>
</div>
</div>
</div>
<div>
<h3 class="text-sm font-bold mb-2">Ocelot Icons</h3>
<div class="grid grid-cols-5 gap-4">
<div v-for="[name, icon] in ocelotEntries" :key="name" class="flex flex-col items-center gap-2 p-3 rounded border border-gray-200">
<OsIcon :icon="icon" size="xl" />
<span class="text-xs text-gray-600">{{ name }}</span>
</div>
<div data-testid="icon-gallery">
<div class="grid grid-cols-5 gap-4">
<div v-for="[name, icon] in allEntries" :key="name" class="flex flex-col items-center gap-2 p-3 rounded border border-gray-200">
<OsIcon :icon="icon" size="xl" />
<span class="text-xs text-gray-600">{{ name }}</span>
</div>
</div>
</div>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.0 KiB

After

Width:  |  Height:  |  Size: 76 KiB

View File

@ -1,13 +1,12 @@
import { mount } from '@vue/test-utils'
import { describe, expect, expectTypeOf, it } from 'vitest'
import { h } from 'vue'
import OsIcon from '#src/components/OsIcon/OsIcon.vue'
import { ocelotIcons } from './index'
describe('ocelot icons', () => {
const IconAngleDown = ocelotIcons.IconAngleDown
const angleDown = ocelotIcons.angleDown
describe('exports', () => {
it('exports ocelotIcons as a record of functions', () => {
@ -17,20 +16,21 @@ describe('ocelot icons', () => {
})
it('auto-discovers all SVGs in svgs/ directory', () => {
expect(ocelotIcons).toHaveProperty('IconAngleDown')
expect(ocelotIcons).toHaveProperty('angleDown')
expect(angleDown).toBeTypeOf('function')
})
expectTypeOf(IconAngleDown).toBeFunction()
it('includes system icons (check, close, plus)', () => {
expect(ocelotIcons).toHaveProperty('check')
expect(ocelotIcons).toHaveProperty('close')
expect(ocelotIcons).toHaveProperty('plus')
})
})
describe('iconAngleDown', () => {
describe('angleDown', () => {
it('renders an SVG with correct viewBox', () => {
const vnode = IconAngleDown()
expect(vnode).toBeDefined()
const wrapper = mount({
render: () => h('div', [IconAngleDown()]),
const wrapper = mount(OsIcon, {
props: { icon: angleDown },
})
const svg = wrapper.find('svg')
@ -40,7 +40,7 @@ describe('ocelot icons', () => {
it('works with OsIcon :icon prop', () => {
const wrapper = mount(OsIcon, {
props: { icon: IconAngleDown },
props: { icon: angleDown },
})
expect(wrapper.find('.os-icon').exists()).toBe(true)
@ -52,7 +52,7 @@ describe('ocelot icons', () => {
describe('keyboard accessibility', () => {
it('icon via :icon prop is not focusable (decorative element)', () => {
const wrapper = mount(OsIcon, {
props: { icon: IconAngleDown },
props: { icon: angleDown },
})
expect(wrapper.attributes('tabindex')).toBeUndefined()

View File

@ -1,24 +1,19 @@
import type { VNode } from 'vue-demi'
import { SYSTEM_ICONS } from '#src/components/OsIcon/icons'
const modules = import.meta.glob<() => VNode>('./svgs/*.svg', {
import type { Component } from 'vue-demi'
const modules = import.meta.glob<Component>('./svgs/*.svg', {
query: '?icon',
eager: true,
import: 'default',
})
function toName(path: string): string {
return (
'Icon' +
path
.replace('./svgs/', '')
.replace('.svg', '')
.split('-')
.filter(Boolean)
.map((s) => s[0].toUpperCase() + s.slice(1))
.join('')
)
const parts = path.replace('./svgs/', '').replace('.svg', '').split('-').filter(Boolean)
return parts.map((s, i) => (i === 0 ? s : s[0].toUpperCase() + s.slice(1))).join('')
}
export const ocelotIcons: Record<string, () => VNode> = Object.fromEntries(
Object.entries(modules).map(([path, icon]) => [toName(path), icon]),
)
export const ocelotIcons: Record<string, Component> = {
...SYSTEM_ICONS,
...Object.fromEntries(Object.entries(modules).map(([path, icon]) => [toName(path), icon])),
}

View File

Before

Width:  |  Height:  |  Size: 275 B

After

Width:  |  Height:  |  Size: 275 B

View File

Before

Width:  |  Height:  |  Size: 294 B

After

Width:  |  Height:  |  Size: 294 B

View File

Before

Width:  |  Height:  |  Size: 294 B

After

Width:  |  Height:  |  Size: 294 B

View File

Before

Width:  |  Height:  |  Size: 293 B

After

Width:  |  Height:  |  Size: 293 B

View File

Before

Width:  |  Height:  |  Size: 820 B

After

Width:  |  Height:  |  Size: 820 B

View File

Before

Width:  |  Height:  |  Size: 468 B

After

Width:  |  Height:  |  Size: 468 B

View File

Before

Width:  |  Height:  |  Size: 230 B

After

Width:  |  Height:  |  Size: 230 B

View File

@ -0,0 +1,4 @@
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<path d="M15 3c1.105 0 2 0.895 2 2 0 0.085-0.021 0.168-0.031 0.25 3.521 0.924 6.031 4.273 6.031 8.031v8.719c0 0.565 0.435 1 1 1h1v2h-7.188c0.114 0.316 0.188 0.647 0.188 1 0 1.645-1.355 3-3 3s-3-1.355-3-3c0-0.353 0.073-0.684 0.188-1h-7.188v-2h1c0.565 0 1-0.435 1-1v-9c0-3.726 2.574-6.866 6.031-7.75-0.010-0.082-0.031-0.165-0.031-0.25 0-1.105 0.895-2 2-2zM14.563 7c-3.118 0.226-5.563 2.824-5.563 6v9c0 0.353-0.073 0.684-0.188 1h12.375c-0.114-0.316-0.188-0.647-0.188-1v-8.719c0-3.319-2.546-6.183-5.813-6.281-0.064-0.002-0.124-0-0.188 0-0.148 0-0.292-0.011-0.438 0zM15 25c-0.564 0-1 0.436-1 1s0.436 1 1 1 1-0.436 1-1-0.436-1-1-1z"/>
<path d="M3.719 2.281l1.438-1.438 26 26-1.438 1.438z"/>
</svg>

After

Width:  |  Height:  |  Size: 790 B

View File

Before

Width:  |  Height:  |  Size: 793 B

After

Width:  |  Height:  |  Size: 793 B

View File

Before

Width:  |  Height:  |  Size: 531 B

After

Width:  |  Height:  |  Size: 531 B

View File

@ -0,0 +1 @@
<!-- Generated by IcoMoon.io --><svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><title>book</title><path d="M10 5c2.92 0 5.482 0.981 6 1.188 0.518-0.206 3.080-1.188 6-1.188 3.227 0 6.375 1.313 6.375 1.313l0.625 0.281v20.406h-11.281c-0.346 0.597-0.979 1-1.719 1s-1.373-0.403-1.719-1h-11.281v-20.406l0.625-0.281s3.148-1.313 6.375-1.313zM10 7c-2.199 0-4.232 0.69-5 0.969v16.125c1.188-0.392 2.897-0.875 5-0.875 2.057 0 3.888 0.506 5 0.875v-16.125c-1-0.343-3.067-0.969-5-0.969zM22 7c-1.933 0-4 0.626-5 0.969v16.125c1.112-0.369 2.943-0.875 5-0.875 2.103 0 3.813 0.483 5 0.875v-16.125c-0.768-0.279-2.801-0.969-5-0.969z"></path></svg>

After

Width:  |  Height:  |  Size: 676 B

View File

Before

Width:  |  Height:  |  Size: 309 B

After

Width:  |  Height:  |  Size: 309 B

View File

Before

Width:  |  Height:  |  Size: 445 B

After

Width:  |  Height:  |  Size: 445 B

View File

Before

Width:  |  Height:  |  Size: 961 B

After

Width:  |  Height:  |  Size: 961 B

View File

Before

Width:  |  Height:  |  Size: 350 B

After

Width:  |  Height:  |  Size: 350 B

View File

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

Before

Width:  |  Height:  |  Size: 388 B

After

Width:  |  Height:  |  Size: 388 B

View File

@ -0,0 +1 @@
<!-- Generated by IcoMoon.io --><svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><title>comments</title><path d="M2 5h20v16h-9.656l-4.719 3.781-1.625 1.313v-5.094h-4v-16zM4 7v12h4v2.906l3.375-2.688 0.281-0.219h8.344v-12h-16zM24 9h6v16h-4v5.094l-6.344-5.094h-9.313l2.5-2h7.5l3.656 2.906v-2.906h4v-12h-4v-2z"></path></svg>

After

Width:  |  Height:  |  Size: 369 B

View File

Before

Width:  |  Height:  |  Size: 252 B

After

Width:  |  Height:  |  Size: 252 B

View File

Before

Width:  |  Height:  |  Size: 302 B

After

Width:  |  Height:  |  Size: 302 B

View File

Before

Width:  |  Height:  |  Size: 610 B

After

Width:  |  Height:  |  Size: 610 B

View File

Before

Width:  |  Height:  |  Size: 374 B

After

Width:  |  Height:  |  Size: 374 B

View File

Before

Width:  |  Height:  |  Size: 375 B

After

Width:  |  Height:  |  Size: 375 B

View File

Before

Width:  |  Height:  |  Size: 264 B

After

Width:  |  Height:  |  Size: 264 B

View File

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 355 B

After

Width:  |  Height:  |  Size: 355 B

View File

Before

Width:  |  Height:  |  Size: 220 B

After

Width:  |  Height:  |  Size: 220 B

View File

Before

Width:  |  Height:  |  Size: 121 KiB

After

Width:  |  Height:  |  Size: 121 KiB

View File

Before

Width:  |  Height:  |  Size: 882 B

After

Width:  |  Height:  |  Size: 882 B

View File

@ -0,0 +1 @@
<!-- Generated by IcoMoon.io --><svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><title>hand-pointer-o</title><path d="M13 2c1.645 0 3 1.355 3 3v4.188c0.316-0.114 0.647-0.188 1-0.188 0.767 0 1.467 0.3 2 0.781 0.533-0.481 1.233-0.781 2-0.781 1.395 0 2.578 0.982 2.906 2.281 0.368-0.163 0.762-0.281 1.188-0.281 1.645 0 3 1.355 3 3v7.813c0 4.533-3.654 8.188-8.188 8.188h-1.719c-1.935 0-3.651-0.675-5-1.688l-0.031-0.063-0.063-0.031-8.188-8.094v-0.031c-1.154-1.154-1.154-3.034 0-4.188s3.034-1.154 4.188 0l0.25 0.219 0.656 0.688v-11.813c0-1.645 1.355-3 3-3zM13 4c-0.555 0-1 0.445-1 1v16.625l-4.313-4.313c-0.446-0.446-0.929-0.446-1.375 0s-0.446 0.929 0 1.375l8.094 8c1.051 0.788 2.317 1.313 3.781 1.313h1.719c3.467 0 6.188-2.721 6.188-6.188v-7.813c0-0.555-0.445-1-1-1s-1 0.445-1 1v2h-2.094v-4c0-0.555-0.445-1-1-1s-1 0.445-1 1v4h-2v-4c0-0.555-0.445-1-1-1s-1 0.445-1 1v4h-2v-11c0-0.555-0.445-1-1-1z"></path></svg>

After

Width:  |  Height:  |  Size: 953 B

View File

@ -0,0 +1 @@
<!-- Generated by IcoMoon.io --><svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><title>heart-o</title><path d="M9.5 5c3.433 0 5.645 2.066 6.5 2.938 0.855-0.871 3.067-2.938 6.5-2.938 4.138 0 7.5 3.404 7.5 7.5 0 2.857-2.469 5.031-2.469 5.031l-11.531 11.563-0.719-0.719-10.813-10.844s-0.619-0.573-1.219-1.469-1.25-2.134-1.25-3.563c0-4.096 3.362-7.5 7.5-7.5zM9.5 7c-3.042 0-5.5 2.496-5.5 5.5 0 0.772 0.423 1.716 0.906 2.438s0.969 1.188 0.969 1.188l10.125 10.125 10.125-10.125s1.875-2.080 1.875-3.625c0-3.004-2.458-5.5-5.5-5.5-2.986 0-5.75 2.906-5.75 2.906l-0.75 0.844-0.75-0.844s-2.764-2.906-5.75-2.906z"></path></svg>

After

Width:  |  Height:  |  Size: 664 B

View File

Before

Width:  |  Height:  |  Size: 334 B

After

Width:  |  Height:  |  Size: 334 B

View File

Before

Width:  |  Height:  |  Size: 425 B

After

Width:  |  Height:  |  Size: 425 B

View File

Before

Width:  |  Height:  |  Size: 468 B

After

Width:  |  Height:  |  Size: 468 B

View File

Before

Width:  |  Height:  |  Size: 293 B

After

Width:  |  Height:  |  Size: 293 B

View File

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

Before

Width:  |  Height:  |  Size: 759 B

After

Width:  |  Height:  |  Size: 759 B

View File

Before

Width:  |  Height:  |  Size: 330 B

After

Width:  |  Height:  |  Size: 330 B

View File

Before

Width:  |  Height:  |  Size: 720 B

After

Width:  |  Height:  |  Size: 720 B

View File

Before

Width:  |  Height:  |  Size: 634 B

After

Width:  |  Height:  |  Size: 634 B

View File

Before

Width:  |  Height:  |  Size: 423 B

After

Width:  |  Height:  |  Size: 423 B

View File

Before

Width:  |  Height:  |  Size: 196 B

After

Width:  |  Height:  |  Size: 196 B

View File

Before

Width:  |  Height:  |  Size: 299 B

After

Width:  |  Height:  |  Size: 299 B

View File

Before

Width:  |  Height:  |  Size: 785 B

After

Width:  |  Height:  |  Size: 785 B

View File

Before

Width:  |  Height:  |  Size: 577 B

After

Width:  |  Height:  |  Size: 577 B

View File

Before

Width:  |  Height:  |  Size: 336 B

After

Width:  |  Height:  |  Size: 336 B

View File

Before

Width:  |  Height:  |  Size: 327 B

After

Width:  |  Height:  |  Size: 327 B

View File

Before

Width:  |  Height:  |  Size: 409 B

After

Width:  |  Height:  |  Size: 409 B

View File

Before

Width:  |  Height:  |  Size: 726 B

After

Width:  |  Height:  |  Size: 726 B

View File

@ -0,0 +1 @@
<!-- Generated by IcoMoon.io --><svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><title>shopping-cart</title><path d="M4.75 7h2.219c0.918 0 1.716 0.61 1.938 1.5l2.625 10.5h11.469l1.906-7h-13.656l-0.5-2h16.75l-2.594 9.531c-0.238 0.87-1.004 1.469-1.906 1.469h-11.469c-0.917 0-1.714-0.61-1.938-1.5l-2.625-10.5h-2.219c-0.552 0-1-0.448-1-1s0.448-1 1-1zM21.75 21c1.645 0 3 1.355 3 3s-1.355 3-3 3-3-1.355-3-3 1.355-3 3-3zM12.75 21c1.645 0 3 1.355 3 3s-1.355 3-3 3-3-1.355-3-3 1.355-3 3-3zM12.75 23c-0.564 0-1 0.436-1 1s0.436 1 1 1 1-0.436 1-1-0.436-1-1-1zM21.75 23c-0.564 0-1 0.436-1 1s0.436 1 1 1 1-0.436 1-1-0.436-1-1-1z"></path></svg>

After

Width:  |  Height:  |  Size: 679 B

View File

Before

Width:  |  Height:  |  Size: 331 B

After

Width:  |  Height:  |  Size: 331 B

View File

Before

Width:  |  Height:  |  Size: 338 B

After

Width:  |  Height:  |  Size: 338 B

View File

Before

Width:  |  Height:  |  Size: 405 B

After

Width:  |  Height:  |  Size: 405 B

View File

Before

Width:  |  Height:  |  Size: 406 B

After

Width:  |  Height:  |  Size: 406 B

View File

Before

Width:  |  Height:  |  Size: 520 B

After

Width:  |  Height:  |  Size: 520 B

View File

Before

Width:  |  Height:  |  Size: 282 B

After

Width:  |  Height:  |  Size: 282 B

View File

Before

Width:  |  Height:  |  Size: 962 B

After

Width:  |  Height:  |  Size: 962 B

View File

Before

Width:  |  Height:  |  Size: 698 B

After

Width:  |  Height:  |  Size: 698 B

View File

Before

Width:  |  Height:  |  Size: 809 B

After

Width:  |  Height:  |  Size: 809 B

View File

Before

Width:  |  Height:  |  Size: 459 B

After

Width:  |  Height:  |  Size: 459 B

View File

Before

Width:  |  Height:  |  Size: 724 B

After

Width:  |  Height:  |  Size: 724 B

View File

Before

Width:  |  Height:  |  Size: 483 B

After

Width:  |  Height:  |  Size: 483 B

View File

Before

Width:  |  Height:  |  Size: 768 B

After

Width:  |  Height:  |  Size: 768 B

View File

Before

Width:  |  Height:  |  Size: 311 B

After

Width:  |  Height:  |  Size: 311 B

View File

@ -7,9 +7,28 @@ const SUFFIX = '?icon'
/** Escape a string for safe embedding in a single-quoted JS literal */
function escapeJS(str: string): string {
return str.replace(/\\/g, '\\\\').replace(/'/g, "\\'")
return str
.replace(/\\/g, '\\\\')
.replace(/'/g, "\\'")
.replace(/\n/g, '\\n')
.replace(/\r/g, '\\r')
.replace(/\u2028/g, '\\u2028')
.replace(/\u2029/g, '\\u2029')
}
const SUPPORTED_ELEMENTS = ['path', 'circle', 'rect', 'polygon', 'polyline', 'ellipse', 'line']
const ELEM_PATTERN = SUPPORTED_ELEMENTS.join('|')
// Built from constant array above — safe to use in RegExp
// eslint-disable-next-line security/detect-non-literal-regexp
const ELEM_REGEX = new RegExp(`<(${ELEM_PATTERN})(?:\\s([^>]*?))?\\/?>`, 'g')
// Elements silently ignored (container without visual effect)
const IGNORED_ELEMENTS = ['g', 'title']
const KNOWN_ELEMENTS = ['svg', ...SUPPORTED_ELEMENTS, ...IGNORED_ELEMENTS]
// Built from constant arrays above — safe to use in RegExp
// eslint-disable-next-line security/detect-non-literal-regexp
const UNSUPPORTED_REGEX = new RegExp(`<(?!\\/|(?:${KNOWN_ELEMENTS.join('|')})\\b)(\\w+)[\\s>]`, 'g')
export default function svgIcon(): Plugin {
return {
name: 'svg-icon',
@ -32,32 +51,43 @@ export default function svgIcon(): Plugin {
const viewBoxMatch = viewBoxRegex.exec(svg)
const viewBox = viewBoxMatch ? viewBoxMatch[1] : '0 0 32 32'
const unsupported = svg.match(/<(?:circle|rect|polygon|polyline|ellipse|line)\s/g)
const unsupported = svg.match(UNSUPPORTED_REGEX)
if (unsupported) {
this.warn(
`${filePath}: unsupported SVG elements will be ignored: ${[...new Set(unsupported.map((s) => s.trim()))].join(', ')}`,
)
}
const paths: string[] = []
const pathRegex = /<path\s[^>]*?\bd="([^"]+)"/g
const children: string[] = []
ELEM_REGEX.lastIndex = 0
let match: RegExpExecArray | null
while ((match = pathRegex.exec(svg)) !== null) {
paths.push(match[1])
while ((match = ELEM_REGEX.exec(svg)) !== null) {
const tag = match[1]
const attrString = match[2] || ''
const attrs: Record<string, string> = {}
const attrRegex = /(\w[\w-]*)=(["'])([^"']*)\2/g
let attrMatch: RegExpExecArray | null
while ((attrMatch = attrRegex.exec(attrString)) !== null) {
attrs[attrMatch[1]] = attrMatch[3]
}
const attrEntries = Object.entries(attrs)
.map(([k, v]) => `'${escapeJS(k)}': '${escapeJS(v)}'`)
.join(', ')
children.push(`_h('${tag}', _v2 ? { attrs: { ${attrEntries} } } : { ${attrEntries} })`)
}
const pathElements = paths
.map((d) => {
const escaped = escapeJS(d)
return `h('path', isVue2 ? { attrs: { d: '${escaped}' } } : { d: '${escaped}' })`
})
.join(', ')
const pathElements = children.join(', ')
const safeViewBox = escapeJS(viewBox)
return `import { h, isVue2 } from 'vue-demi'
// Icon functions accept optional (h, v2) from OsIcon. When OsIcon passes
// Vue 2's $createElement, we use it directly — avoiding the globally-imported
// h() which requires currentInstance in Vue 2.7.
// When used as a standalone Vue 3 component (e.g. in Storybook), h/v2 are not
// functions/booleans, so we fall back to the imported _hImport / _v2Import.
return `import { h as _hImport, isVue2 as _v2Import } from 'vue-demi'
const svgAttrs = { xmlns: 'http://www.w3.org/2000/svg', viewBox: '${safeViewBox}', fill: 'currentColor' }
export default () => h('svg', isVue2 ? { attrs: svgAttrs } : svgAttrs, [${pathElements}])
export default (h, v2) => { const _h = typeof h === 'function' ? h : _hImport; const _v2 = typeof v2 === 'boolean' ? v2 : _v2Import; return _h('svg', _v2 ? { attrs: svgAttrs } : svgAttrs, [${pathElements}]) }
`
},
}

View File

@ -0,0 +1,9 @@
import { config } from '@vue/test-utils'
config.global.config.warnHandler = (msg) => {
throw new Error(`[Vue warn]: ${msg}`)
}
config.global.config.errorHandler = (err) => {
throw err instanceof Error ? err : new Error(`[Vue error]: ${String(err)}`)
}

View File

@ -68,6 +68,7 @@ export default defineConfig({
test: {
globals: true,
environment: 'jsdom',
setupFiles: ['src/test/setup.ts'],
include: ['src/**/*.{test,spec}.{js,ts}'],
exclude: ['src/**/*.visual.spec.ts', 'src/plugins/**'],
coverage: {

View File

View File

@ -1,5 +0,0 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<title>angle-down</title>
<path d="M4.219 10.781l11.781 11.781 11.781-11.781 1.438 1.438-12.5 12.5-0.719 0.688-0.719-0.688-12.5-12.5z"></path>
</svg>

Before

Width:  |  Height:  |  Size: 281 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="1080" height="1080"><rect width="100%" height="100%" fill="transparent"/><path d="M15 3a2 2 0 0 1 2 2c0 .085-.021.168-.031.25C20.49 6.174 23 9.523 23 13.281V22c0 .565.435 1 1 1h1v2h-7.188c.114.316.188.647.188 1 0 1.645-1.355 3-3 3s-3-1.355-3-3c0-.353.073-.684.188-1H5v-2h1c.565 0 1-.435 1-1v-9c0-3.726 2.574-6.866 6.031-7.75C13.021 5.168 13 5.085 13 5a2 2 0 0 1 2-2zm-.437 4A6.004 6.004 0 0 0 9 13v9c0 .353-.073.684-.188 1h12.375a2.925 2.925 0 0 1-.188-1v-8.719c0-3.319-2.546-6.183-5.813-6.281-.064-.002-.124 0-.188 0-.148 0-.292-.011-.438 0zM15 25c-.564 0-1 .436-1 1 0 .564.436 1 1 1 .564 0 1-.436 1-1 0-.564-.436-1-1-1z" style="stroke:none;stroke-width:1;stroke-dasharray:none;stroke-linecap:butt;stroke-dashoffset:0;stroke-linejoin:miter;stroke-miterlimit:4;fill:#000;fill-rule:nonzero;opacity:1" transform="translate(33.75) scale(33.75)"/><rect width="74.334" height="74.334" x="-37.167" y="-37.167" rx="0" ry="0" style="stroke:#000;stroke-width:0;stroke-dasharray:none;stroke-linecap:butt;stroke-dashoffset:0;stroke-linejoin:miter;stroke-miterlimit:4;fill:#000;fill-rule:nonzero;opacity:1" transform="matrix(9.42 -12.59 .8 .6 538.54 541.95)" vector-effect="non-scaling-stroke"/></svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -1,5 +0,0 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<title>book</title>
<path d="M10 5c2.92 0 5.482 0.981 6 1.188 0.518-0.206 3.080-1.188 6-1.188 3.227 0 6.375 1.313 6.375 1.313l0.625 0.281v20.406h-11.281c-0.346 0.597-0.979 1-1.719 1s-1.373-0.403-1.719-1h-11.281v-20.406l0.625-0.281s3.148-1.313 6.375-1.313zM10 7c-2.199 0-4.232 0.69-5 0.969v16.125c1.188-0.392 2.897-0.875 5-0.875 2.057 0 3.888 0.506 5 0.875v-16.125c-1-0.343-3.067-0.969-5-0.969zM22 7c-1.933 0-4 0.626-5 0.969v16.125c1.112-0.369 2.943-0.875 5-0.875 2.103 0 3.813 0.483 5 0.875v-16.125c-0.768-0.279-2.801-0.969-5-0.969z"></path>
</svg>

Before

Width:  |  Height:  |  Size: 680 B

View File

@ -1,5 +1 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<title>bullhorn</title>
<path d="M28 3.031v9.156c1.156 0.418 2 1.521 2 2.813s-0.844 2.394-2 2.813v9.156l-1.594-1.156s-2.007-1.443-4.875-2.906-6.587-2.906-9.813-2.906h-3.375l1.625 5.719 0.344 1.281h-6.063l-0.219-0.719-2-7-0.031-0.156v-9.125h9.719c3.27 0 6.987-1.412 9.844-2.875s4.844-2.938 4.844-2.938zM26 6.75c-0.82 0.558-1.459 1.064-3.531 2.125-2.929 1.5-6.726 3.050-10.469 3.125v6c3.708 0.073 7.499 1.595 10.438 3.094 2.078 1.060 2.735 1.567 3.563 2.125v-16.469zM4 12v6h6v-6h-6zM4.344 20l1.406 5h1.906l-1.406-5h-1.906z"></path>
</svg>
<!-- Generated by IcoMoon.io --><svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><title>bullhorn</title><path d="M28 3.031v9.156c1.156 0.418 2 1.521 2 2.813s-0.844 2.394-2 2.813v9.156l-1.594-1.156s-2.007-1.443-4.875-2.906-6.587-2.906-9.813-2.906h-3.375l1.625 5.719 0.344 1.281h-6.063l-0.219-0.719-2-7-0.031-0.156v-9.125h9.719c3.27 0 6.987-1.412 9.844-2.875s4.844-2.938 4.844-2.938zM26 6.75c-0.82 0.558-1.459 1.064-3.531 2.125-2.929 1.5-6.726 3.050-10.469 3.125v6c3.708 0.073 7.499 1.595 10.438 3.094 2.078 1.060 2.735 1.567 3.563 2.125v-16.469zM4 12v6h6v-6h-6zM4.344 20l1.406 5h1.906l-1.406-5h-1.906z"></path></svg>

Before

Width:  |  Height:  |  Size: 668 B

After

Width:  |  Height:  |  Size: 664 B

View File

@ -1,5 +1 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<title>camera</title>
<path d="M11.5 6h9l0.313 0.406 1.188 1.594h7v18h-26v-18h7l1.188-1.594zM12.5 8l-1.188 1.594-0.313 0.406h-6v14h22v-14h-6l-0.313-0.406-1.188-1.594h-7zM8 11c0.552 0 1 0.448 1 1s-0.448 1-1 1-1-0.448-1-1 0.448-1 1-1zM16 11c3.302 0 6 2.698 6 6s-2.698 6-6 6-6-2.698-6-6 2.698-6 6-6zM16 13c-2.221 0-4 1.779-4 4s1.779 4 4 4 4-1.779 4-4-1.779-4-4-4z"></path>
</svg>
<!-- Generated by IcoMoon.io --><svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><title>camera</title><path d="M11.5 6h9l0.313 0.406 1.188 1.594h7v18h-26v-18h7l1.188-1.594zM12.5 8l-1.188 1.594-0.313 0.406h-6v14h22v-14h-6l-0.313-0.406-1.188-1.594h-7zM8 11c0.552 0 1 0.448 1 1s-0.448 1-1 1-1-0.448-1-1 0.448-1 1-1zM16 11c3.302 0 6 2.698 6 6s-2.698 6-6 6-6-2.698-6-6 2.698-6 6-6zM16 13c-2.221 0-4 1.779-4 4s1.779 4 4 4 4-1.779 4-4-1.779-4-4-4z"></path></svg>

Before

Width:  |  Height:  |  Size: 508 B

After

Width:  |  Height:  |  Size: 504 B

View File

@ -1,5 +1 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<title>child</title>
<path d="M12 3c2.202 0 3.791 1.007 4.531 2.313 0.026-0.041 0.034-0.084 0.063-0.125 0.453-0.641 1.315-1.188 2.406-1.188v2c-0.453 0-0.588 0.111-0.719 0.281 3.845 0.921 6.812 4.105 7.563 8.063 1.193 0.397 2.156 1.337 2.156 2.656 0 1.365-1.024 2.33-2.281 2.688-0.816 4.701-4.82 8.313-9.719 8.313s-8.903-3.611-9.719-8.313c-1.257-0.357-2.281-1.323-2.281-2.688s1.024-2.33 2.281-2.688c0.741-4.271 4.122-7.637 8.406-8.219-0.39-0.574-1.192-1.094-2.688-1.094v-2zM16 8c-4.093 0-7.461 3.121-7.906 7.125l-0.094 0.875h-1c-0.555 0-1 0.445-1 1s0.445 1 1 1h1l0.094 0.875c0.445 4.004 3.813 7.125 7.906 7.125s7.461-3.121 7.906-7.125l0.094-0.875h1c0.555 0 1-0.445 1-1s-0.445-1-1-1h-0.875l-0.125-0.875c-0.536-4.019-3.907-7.125-8-7.125zM12.5 16c0.828 0 1.5 0.672 1.5 1.5s-0.672 1.5-1.5 1.5-1.5-0.672-1.5-1.5 0.672-1.5 1.5-1.5zM19.5 16c0.828 0 1.5 0.672 1.5 1.5s-0.672 1.5-1.5 1.5-1.5-0.672-1.5-1.5 0.672-1.5 1.5-1.5z"></path>
</svg>
<!-- Generated by IcoMoon.io --><svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><title>child</title><path d="M12 3c2.202 0 3.791 1.007 4.531 2.313 0.026-0.041 0.034-0.084 0.063-0.125 0.453-0.641 1.315-1.188 2.406-1.188v2c-0.453 0-0.588 0.111-0.719 0.281 3.845 0.921 6.812 4.105 7.563 8.063 1.193 0.397 2.156 1.337 2.156 2.656 0 1.365-1.024 2.33-2.281 2.688-0.816 4.701-4.82 8.313-9.719 8.313s-8.903-3.611-9.719-8.313c-1.257-0.357-2.281-1.323-2.281-2.688s1.024-2.33 2.281-2.688c0.741-4.271 4.122-7.637 8.406-8.219-0.39-0.574-1.192-1.094-2.688-1.094v-2zM16 8c-4.093 0-7.461 3.121-7.906 7.125l-0.094 0.875h-1c-0.555 0-1 0.445-1 1s0.445 1 1 1h1l0.094 0.875c0.445 4.004 3.813 7.125 7.906 7.125s7.461-3.121 7.906-7.125l0.094-0.875h1c0.555 0 1-0.445 1-1s-0.445-1-1-1h-0.875l-0.125-0.875c-0.536-4.019-3.907-7.125-8-7.125zM12.5 16c0.828 0 1.5 0.672 1.5 1.5s-0.672 1.5-1.5 1.5-1.5-0.672-1.5-1.5 0.672-1.5 1.5-1.5zM19.5 16c0.828 0 1.5 0.672 1.5 1.5s-0.672 1.5-1.5 1.5-1.5-0.672-1.5-1.5 0.672-1.5 1.5-1.5z"></path></svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -1,5 +0,0 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<title>comments</title>
<path d="M2 5h20v16h-9.656l-4.719 3.781-1.625 1.313v-5.094h-4v-16zM4 7v12h4v2.906l3.375-2.688 0.281-0.219h8.344v-12h-16zM24 9h6v16h-4v5.094l-6.344-5.094h-9.313l2.5-2h7.5l3.656 2.906v-2.906h4v-12h-4v-2z"></path>
</svg>

Before

Width:  |  Height:  |  Size: 373 B

View File

@ -1,5 +1 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<title>credit-card</title>
<path d="M5 5h18c1.645 0 3 1.355 3 3v1h1c1.645 0 3 1.355 3 3v12c0 1.645-1.355 3-3 3h-18c-1.645 0-3-1.355-3-3v-1h-1c-1.645 0-3-1.355-3-3v-12c0-1.645 1.355-3 3-3zM5 7c-0.565 0-1 0.435-1 1v12c0 0.565 0.435 1 1 1h18c0.565 0 1-0.435 1-1v-9h-19v-2h19v-1c0-0.565-0.435-1-1-1h-18zM26 11v2h2v-1c0-0.565-0.435-1-1-1h-1zM26 15v5c0 1.645-1.355 3-3 3h-15v1c0 0.565 0.435 1 1 1h18c0.565 0 1-0.435 1-1v-9h-2z"></path>
</svg>
<!-- Generated by IcoMoon.io --><svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><title>credit-card</title><path d="M5 5h18c1.645 0 3 1.355 3 3v1h1c1.645 0 3 1.355 3 3v12c0 1.645-1.355 3-3 3h-18c-1.645 0-3-1.355-3-3v-1h-1c-1.645 0-3-1.355-3-3v-12c0-1.645 1.355-3 3-3zM5 7c-0.565 0-1 0.435-1 1v12c0 0.565 0.435 1 1 1h18c0.565 0 1-0.435 1-1v-9h-19v-2h19v-1c0-0.565-0.435-1-1-1h-18zM26 11v2h2v-1c0-0.565-0.435-1-1-1h-1zM26 15v5c0 1.645-1.355 3-3 3h-15v1c0 0.565 0.435 1 1 1h18c0.565 0 1-0.435 1-1v-9h-2z"></path></svg>

Before

Width:  |  Height:  |  Size: 568 B

After

Width:  |  Height:  |  Size: 564 B

View File

@ -1,5 +1 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<title>cubes</title>
<path d="M16 4l0.375 0.156 6.625 2.656v6.719l5.406 2.344 0.594 0.281v8.063l-0.5 0.313-6 3.344-0.469 0.25-0.469-0.219-5.563-2.781-5.563 2.781-0.469 0.219-0.469-0.25-6-3.344-0.5-0.313v-8.063l0.594-0.281 5.406-2.344v-6.719l6.625-2.656zM16 6.188l-3.281 1.281 3.281 1.281 3.281-1.281zM11 8.938v4.625l4 1.781v-4.875zM21 8.938l-4 1.531v4.875l4-1.781v-4.625zM10 15.313l-3.625 1.563 3.625 1.813 3.625-1.781zM22 15.313l-2.5 1.094-1.125 0.5 3.625 1.781 3.625-1.813zM5 18.406v4.656l4 2.25v-4.906zM27 18.406l-4 2v4.906l4-2.25v-4.656zM15 18.469l-4 1.938v4.969l4-2v-4.906zM17 18.469v4.906l4 2v-4.969z"></path>
</svg>
<!-- Generated by IcoMoon.io --><svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><title>cubes</title><path d="M16 4l0.375 0.156 6.625 2.656v6.719l5.406 2.344 0.594 0.281v8.063l-0.5 0.313-6 3.344-0.469 0.25-0.469-0.219-5.563-2.781-5.563 2.781-0.469 0.219-0.469-0.25-6-3.344-0.5-0.313v-8.063l0.594-0.281 5.406-2.344v-6.719l6.625-2.656zM16 6.188l-3.281 1.281 3.281 1.281 3.281-1.281zM11 8.938v4.625l4 1.781v-4.875zM21 8.938l-4 1.531v4.875l4-1.781v-4.625zM10 15.313l-3.625 1.563 3.625 1.813 3.625-1.781zM22 15.313l-2.5 1.094-1.125 0.5 3.625 1.781 3.625-1.813zM5 18.406v4.656l4 2.25v-4.906zM27 18.406l-4 2v4.906l4-2.25v-4.656zM15 18.469l-4 1.938v4.969l4-2v-4.906zM17 18.469v4.906l4 2v-4.969z"></path></svg>

Before

Width:  |  Height:  |  Size: 754 B

After

Width:  |  Height:  |  Size: 750 B

View File

@ -1,20 +1 @@
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32px" height="32px" viewBox="0 0 32 32">
<path d="M5.9,25.1c-0.3,0.3-0.3,0.8,0,1.1s0.8,0.3,1.1,0c1.7-1.7,4.5-1.7,6.3,0c0.1,0.1,0.3,0.2,0.5,0.2s0.4-0.1,0.5-0.2
c0.3-0.3,0.3-0.8,0-1.1C12,22.8,8.2,22.8,5.9,25.1z"/>
<path d="M24.4,8.7c0.7-0.7,2-0.7,2.7,0C27.2,8.9,27.4,9,27.6,9c0.2,0,0.4-0.1,0.5-0.2c0.3-0.3,0.3-0.8,0-1.1
c-1.3-1.3-3.5-1.3-4.8,0C23,8,23,8.5,23.3,8.7C23.6,9,24.1,9,24.4,8.7z"/>
<path d="M16.4,7.7c-0.3,0.3-0.3,0.8,0,1.1c0.3,0.3,0.8,0.3,1.1,0c0.7-0.7,1.9-0.7,2.7,0C20.3,8.9,20.5,9,20.7,9s0.4-0.1,0.5-0.2
c0.3-0.3,0.3-0.8,0-1.1C19.9,6.4,17.7,6.4,16.4,7.7z"/>
<path d="M31.4,0.8c-0.2-0.1-0.5-0.2-0.7-0.1c-2,0.8-5.1,1.2-8.4,1.2s-6.4-0.4-8.4-1.2c-0.2-0.1-0.5-0.1-0.7,0.1
c-0.2,0.1-0.3,0.4-0.3,0.6v9.9c-1,0.1-1.9,0.1-3,0.1c-3.3,0-6.4-0.4-8.4-1.2c-0.2-0.1-0.5-0.1-0.7,0.1c-0.2,0.1-0.3,0.4-0.3,0.6
l0,11.5c0,5.2,4.2,9.4,9.4,9.4s9.4-4.2,9.4-9.4V22c0.7,0.3,1.6,0.4,3,0.4c5.2,0,9.4-4.2,9.4-9.4V1.4C31.7,1.2,31.6,0.9,31.4,0.8z
M9.9,30.4c-4.4,0-7.9-3.6-7.9-7.9V12c2.1,0.6,4.9,1,7.9,1c2.7,0,5.2-0.3,7.3-0.8l0.5-0.1c0,1.6,0,2.9,0,4c0,1.3,0,2.4,0.1,3.2v3.2
C17.8,26.8,14.2,30.4,9.9,30.4z M30.2,13c0,4.4-3.6,7.9-7.9,7.9c-2.1,0-2.8,0-3-1.7v-2.8c0.9,0.5,1.9,0.8,3,0.8
c1.6,0,3.1-0.6,4.2-1.7c0.3-0.3,0.3-0.8,0-1.1s-0.8-0.3-1.1,0c-0.8,0.8-2,1.3-3.1,1.3c-1.1,0-2.1-0.4-3-1.2v-3.6
c0-0.2-0.1-0.5-0.3-0.6c-0.2-0.1-0.5-0.2-0.7-0.1c-0.4,0.2-0.9,0.3-1.4,0.4l-2.5,0.4V2.5c2.1,0.6,4.9,1,7.9,1c3,0,5.8-0.3,7.9-1V13
z"/>
<path d="M10.9,17.7c-0.3,0.3-0.3,0.8,0,1.1s0.8,0.3,1.1,0c0.7-0.7,2-0.7,2.7,0c0.1,0.1,0.3,0.2,0.5,0.2s0.4-0.1,0.5-0.2
c0.3-0.3,0.3-0.8,0-1.1C14.4,16.4,12.2,16.4,10.9,17.7z"/>
<path d="M7.7,18.7C7.9,18.9,8.1,19,8.3,19s0.4-0.1,0.5-0.2c0.3-0.3,0.3-0.8,0-1.1c-1.3-1.3-3.5-1.3-4.8,0c-0.3,0.3-0.3,0.8,0,1.1
s0.8,0.3,1.1,0C5.8,18,7,18,7.7,18.7z"/>
</svg>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32px" height="32px" viewBox="0 0 32 32"><path d="M5.9,25.1c-0.3,0.3-0.3,0.8,0,1.1s0.8,0.3,1.1,0c1.7-1.7,4.5-1.7,6.3,0c0.1,0.1,0.3,0.2,0.5,0.2s0.4-0.1,0.5-0.2 c0.3-0.3,0.3-0.8,0-1.1C12,22.8,8.2,22.8,5.9,25.1z"/><path d="M24.4,8.7c0.7-0.7,2-0.7,2.7,0C27.2,8.9,27.4,9,27.6,9c0.2,0,0.4-0.1,0.5-0.2c0.3-0.3,0.3-0.8,0-1.1 c-1.3-1.3-3.5-1.3-4.8,0C23,8,23,8.5,23.3,8.7C23.6,9,24.1,9,24.4,8.7z"/><path d="M16.4,7.7c-0.3,0.3-0.3,0.8,0,1.1c0.3,0.3,0.8,0.3,1.1,0c0.7-0.7,1.9-0.7,2.7,0C20.3,8.9,20.5,9,20.7,9s0.4-0.1,0.5-0.2 c0.3-0.3,0.3-0.8,0-1.1C19.9,6.4,17.7,6.4,16.4,7.7z"/><path d="M31.4,0.8c-0.2-0.1-0.5-0.2-0.7-0.1c-2,0.8-5.1,1.2-8.4,1.2s-6.4-0.4-8.4-1.2c-0.2-0.1-0.5-0.1-0.7,0.1 c-0.2,0.1-0.3,0.4-0.3,0.6v9.9c-1,0.1-1.9,0.1-3,0.1c-3.3,0-6.4-0.4-8.4-1.2c-0.2-0.1-0.5-0.1-0.7,0.1c-0.2,0.1-0.3,0.4-0.3,0.6 l0,11.5c0,5.2,4.2,9.4,9.4,9.4s9.4-4.2,9.4-9.4V22c0.7,0.3,1.6,0.4,3,0.4c5.2,0,9.4-4.2,9.4-9.4V1.4C31.7,1.2,31.6,0.9,31.4,0.8z M9.9,30.4c-4.4,0-7.9-3.6-7.9-7.9V12c2.1,0.6,4.9,1,7.9,1c2.7,0,5.2-0.3,7.3-0.8l0.5-0.1c0,1.6,0,2.9,0,4c0,1.3,0,2.4,0.1,3.2v3.2 C17.8,26.8,14.2,30.4,9.9,30.4z M30.2,13c0,4.4-3.6,7.9-7.9,7.9c-2.1,0-2.8,0-3-1.7v-2.8c0.9,0.5,1.9,0.8,3,0.8 c1.6,0,3.1-0.6,4.2-1.7c0.3-0.3,0.3-0.8,0-1.1s-0.8-0.3-1.1,0c-0.8,0.8-2,1.3-3.1,1.3c-1.1,0-2.1-0.4-3-1.2v-3.6 c0-0.2-0.1-0.5-0.3-0.6c-0.2-0.1-0.5-0.2-0.7-0.1c-0.4,0.2-0.9,0.3-1.4,0.4l-2.5,0.4V2.5c2.1,0.6,4.9,1,7.9,1c3,0,5.8-0.3,7.9-1V13 z"/><path d="M10.9,17.7c-0.3,0.3-0.3,0.8,0,1.1s0.8,0.3,1.1,0c0.7-0.7,2-0.7,2.7,0c0.1,0.1,0.3,0.2,0.5,0.2s0.4-0.1,0.5-0.2 c0.3-0.3,0.3-0.8,0-1.1C14.4,16.4,12.2,16.4,10.9,17.7z"/><path d="M7.7,18.7C7.9,18.9,8.1,19,8.3,19s0.4-0.1,0.5-0.2c0.3-0.3,0.3-0.8,0-1.1c-1.3-1.3-3.5-1.3-4.8,0c-0.3,0.3-0.3,0.8,0,1.1 s0.8,0.3,1.1,0C5.8,18,7,18,7.7,18.7z"/></svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -1,14 +1 @@
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" width="32px" height="32px" viewBox="0 0 32 32">
<path d="M27.6,19.7L26.8,19c-3-2.8-4.8-4.4-5.2-4.6c-0.9-0.6-2.9-0.5-3.6-0.4c-0.2-0.5-0.5-0.9-0.9-1.2V2.2
c0-1-0.7-1.6-1.3-1.6c-0.6-0.1-1.4,0.4-1.6,1.4c-0.1,0.5-0.3,1.4-0.5,2.4c-0.6,2.9-1,5-1,5.4c-0.1,1.1,1.1,2.8,1.5,3.3
c-0.3,0.4-0.5,0.9-0.5,1.4c0,0,0,0,0,0.1c-0.9,0.6-7.3,5-8.7,6c-0.8,0.6-0.9,1.4-0.6,2c0.2,0.4,0.7,0.7,1.2,0.7
c0.3,0,0.5-0.1,0.8-0.2c1.5-0.6,6.7-2.9,7.4-3.2c0.2-0.1,0.4-0.3,0.6-0.5l-1.3,11c0,1,2.3,1,2.8,1s2.8,0,2.8-1.1l-1.4-13.5
c1.8,1.1,7.2,4.4,8.6,5.2c0.3,0.2,0.7,0.3,0.9,0.3c0.5,0,0.9-0.2,1.1-0.5C28.5,21.4,28.5,20.5,27.6,19.7z M14.8,14.6
c0-0.8,0.6-1.2,1.2-1.2c0.6,0,1.2,0.6,1.2,1.2c0,0.8-0.6,1.2-1.2,1.2C15.2,15.8,14.8,15.2,14.8,14.6z M14.8,4.7c0.2-1,0.4-2,0.5-2.5
c0.1-0.5,0.3-0.7,0.5-0.6c0.2,0,0.4,0.2,0.4,0.6v10.2c-0.1,0-0.1,0-0.2,0c-0.3,0-0.6,0.1-0.9,0.2c-0.6-0.8-1.4-2-1.3-2.7
C13.8,9.5,14.4,6.5,14.8,4.7z M13.5,19.1c-0.6,0.3-5.8,2.6-7.3,3.2c-0.4,0.2-0.7,0.1-0.8-0.1c-0.1-0.2,0-0.4,0.3-0.7
c1.3-0.9,6.9-4.8,8.4-5.8c0.2,0.3,0.5,0.6,0.8,0.8C14.6,17.4,13.9,18.8,13.5,19.1z M16,30.4c-0.6,0-1.4-0.1-1.8-0.2l1.6-13.4
c0,0,0.1,0,0.1,0c0.1,0,0.3,0,0.4,0l1.4,13.4C17.4,30.3,16.6,30.4,16,30.4z M27.3,21.3c-0.1,0.1-0.4,0.2-0.7,0
c-1.5-0.9-7.2-4.4-8.8-5.3c0.2-0.3,0.3-0.6,0.4-0.9c1-0.1,2.5-0.1,3,0.3c0.4,0.2,3.6,3.2,5,4.5l0.8,0.7
C27.3,20.8,27.4,21.1,27.3,21.3z"/>
</svg>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" width="32px" height="32px" viewBox="0 0 32 32"><path d="M27.6,19.7L26.8,19c-3-2.8-4.8-4.4-5.2-4.6c-0.9-0.6-2.9-0.5-3.6-0.4c-0.2-0.5-0.5-0.9-0.9-1.2V2.2 c0-1-0.7-1.6-1.3-1.6c-0.6-0.1-1.4,0.4-1.6,1.4c-0.1,0.5-0.3,1.4-0.5,2.4c-0.6,2.9-1,5-1,5.4c-0.1,1.1,1.1,2.8,1.5,3.3 c-0.3,0.4-0.5,0.9-0.5,1.4c0,0,0,0,0,0.1c-0.9,0.6-7.3,5-8.7,6c-0.8,0.6-0.9,1.4-0.6,2c0.2,0.4,0.7,0.7,1.2,0.7 c0.3,0,0.5-0.1,0.8-0.2c1.5-0.6,6.7-2.9,7.4-3.2c0.2-0.1,0.4-0.3,0.6-0.5l-1.3,11c0,1,2.3,1,2.8,1s2.8,0,2.8-1.1l-1.4-13.5 c1.8,1.1,7.2,4.4,8.6,5.2c0.3,0.2,0.7,0.3,0.9,0.3c0.5,0,0.9-0.2,1.1-0.5C28.5,21.4,28.5,20.5,27.6,19.7z M14.8,14.6 c0-0.8,0.6-1.2,1.2-1.2c0.6,0,1.2,0.6,1.2,1.2c0,0.8-0.6,1.2-1.2,1.2C15.2,15.8,14.8,15.2,14.8,14.6z M14.8,4.7c0.2-1,0.4-2,0.5-2.5 c0.1-0.5,0.3-0.7,0.5-0.6c0.2,0,0.4,0.2,0.4,0.6v10.2c-0.1,0-0.1,0-0.2,0c-0.3,0-0.6,0.1-0.9,0.2c-0.6-0.8-1.4-2-1.3-2.7 C13.8,9.5,14.4,6.5,14.8,4.7z M13.5,19.1c-0.6,0.3-5.8,2.6-7.3,3.2c-0.4,0.2-0.7,0.1-0.8-0.1c-0.1-0.2,0-0.4,0.3-0.7 c1.3-0.9,6.9-4.8,8.4-5.8c0.2,0.3,0.5,0.6,0.8,0.8C14.6,17.4,13.9,18.8,13.5,19.1z M16,30.4c-0.6,0-1.4-0.1-1.8-0.2l1.6-13.4 c0,0,0.1,0,0.1,0c0.1,0,0.3,0,0.4,0l1.4,13.4C17.4,30.3,16.6,30.4,16,30.4z M27.3,21.3c-0.1,0.1-0.4,0.2-0.7,0 c-1.5-0.9-7.2-4.4-8.8-5.3c0.2-0.3,0.3-0.6,0.4-0.9c1-0.1,2.5-0.1,3,0.3c0.4,0.2,3.6,3.2,5,4.5l0.8,0.7 C27.3,20.8,27.4,21.1,27.3,21.3z"/></svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -1,13 +1 @@
<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" width="32px" height="32px" viewBox="0 0 32 32">
<rect x="8.1" y="13.3" width="1.5" height="1.9"/>
<path d="M31.9,17.9L31.9,17.9l0-0.6c-0.2-5.5-4.1-10.3-9.5-11.6c-0.2,0-0.8-0.2-0.8-0.2c-3.1-0.6-6.3-0.5-9.5,0.1
c-0.3,0.1-0.6,0.1-0.9,0.2C10.6,5.7,10,5.4,9.7,5.4L9.5,5.3C8.7,5,7.6,4.6,6.8,5.1C6,5.7,6,6.7,6.2,7.3l0.3,1.2
C5.1,9.7,4,11.2,3.3,12.8c-0.4,0.8-0.8,0.8-1.2,0.8c-0.1,0-0.2,0-0.3,0H0l0,5.5l0.6,0.1c0,0,1.1,0.2,1.6,1C2.5,20.7,2.7,21,3,22.3
c1.1,3.4,3.6,5.3,4.6,5.9l0,3.9H12l2.6-3.4h6.1l1.7,3.4h4.9v-4.6l0.4-0.4c2.5-2.2,3.9-5.2,4.1-8.5l0-0.4
C31.9,18.1,31.9,18,31.9,17.9z M26.7,25.9l-0.9,0.9v3.8h-2.5l-1.7-3.4h-7.7l-2.6,3.4H9.1l0-3.2l-0.4-0.2c0,0-3.1-1.7-4.2-5.3
c-0.4-1.4-0.6-1.8-1-2.3c-0.5-0.9-1.4-1.3-2-1.5v-2.8l0.6,0c0.5,0,1.8,0,2.6-1.7c0.5-1.2,1.3-2.3,2.2-3.3c0.8-0.8,1.3-1,1.1-1.5
l0,0L7.6,7c-0.1-0.2-0.1-0.5,0-0.6c0.2-0.1,1,0.1,1.4,0.3l0.3,0.1c0.3,0.1,0.9,0.4,1.7,0.6l0.2,0.1l0.3-0.1c0.3-0.1,0.7-0.2,1-0.2
c3-0.6,5.9-0.6,8.9-0.1c0,0,0.6,0.1,0.8,0.1c4.7,1.1,8.2,5.3,8.4,10.1l0,0.8c-0.1,1.3-1.2,2.4-2.5,2.4c-1,0-1.9-0.9-1.9-2
c0-0.8,0.6-1.4,1.4-1.4v-1.5c-1.6,0-2.9,1.3-2.9,2.9c0,1.9,1.5,3.5,3.4,3.5c0.7,0,1.3-0.2,1.8-0.5C29.1,23.2,28.1,24.7,26.7,25.9z"
/>
</svg>
<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" width="32px" height="32px" viewBox="0 0 32 32"><rect x="8.1" y="13.3" width="1.5" height="1.9"/><path d="M31.9,17.9L31.9,17.9l0-0.6c-0.2-5.5-4.1-10.3-9.5-11.6c-0.2,0-0.8-0.2-0.8-0.2c-3.1-0.6-6.3-0.5-9.5,0.1 c-0.3,0.1-0.6,0.1-0.9,0.2C10.6,5.7,10,5.4,9.7,5.4L9.5,5.3C8.7,5,7.6,4.6,6.8,5.1C6,5.7,6,6.7,6.2,7.3l0.3,1.2 C5.1,9.7,4,11.2,3.3,12.8c-0.4,0.8-0.8,0.8-1.2,0.8c-0.1,0-0.2,0-0.3,0H0l0,5.5l0.6,0.1c0,0,1.1,0.2,1.6,1C2.5,20.7,2.7,21,3,22.3 c1.1,3.4,3.6,5.3,4.6,5.9l0,3.9H12l2.6-3.4h6.1l1.7,3.4h4.9v-4.6l0.4-0.4c2.5-2.2,3.9-5.2,4.1-8.5l0-0.4 C31.9,18.1,31.9,18,31.9,17.9z M26.7,25.9l-0.9,0.9v3.8h-2.5l-1.7-3.4h-7.7l-2.6,3.4H9.1l0-3.2l-0.4-0.2c0,0-3.1-1.7-4.2-5.3 c-0.4-1.4-0.6-1.8-1-2.3c-0.5-0.9-1.4-1.3-2-1.5v-2.8l0.6,0c0.5,0,1.8,0,2.6-1.7c0.5-1.2,1.3-2.3,2.2-3.3c0.8-0.8,1.3-1,1.1-1.5 l0,0L7.6,7c-0.1-0.2-0.1-0.5,0-0.6c0.2-0.1,1,0.1,1.4,0.3l0.3,0.1c0.3,0.1,0.9,0.4,1.7,0.6l0.2,0.1l0.3-0.1c0.3-0.1,0.7-0.2,1-0.2 c3-0.6,5.9-0.6,8.9-0.1c0,0,0.6,0.1,0.8,0.1c4.7,1.1,8.2,5.3,8.4,10.1l0,0.8c-0.1,1.3-1.2,2.4-2.5,2.4c-1,0-1.9-0.9-1.9-2 c0-0.8,0.6-1.4,1.4-1.4v-1.5c-1.6,0-2.9,1.3-2.9,2.9c0,1.9,1.5,3.5,3.4,3.5c0.7,0,1.3-0.2,1.8-0.5C29.1,23.2,28.1,24.7,26.7,25.9z" /></svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -1,5 +1 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<title>graduation-cap</title>
<path d="M16 6.781l0.313 0.094 15.344 5.125-2.844 0.938-2.813 0.938v5.125c0 0.82-0.499 1.5-1.094 1.969s-1.332 0.798-2.219 1.094c-1.773 0.591-4.112 0.938-6.688 0.938s-4.914-0.346-6.688-0.938c-0.887-0.296-1.624-0.625-2.219-1.094s-1.094-1.149-1.094-1.969v-5.125l-2-0.656v8.063c0.597 0.346 1 0.979 1 1.719 0 1.105-0.895 2-2 2s-2-0.895-2-2c0-0.74 0.403-1.373 1-1.719v-8.75l-1.656-0.531 2.844-0.938 12.5-4.188zM16 8.875l-9.375 3.125 9.375 3.125 9.375-3.125zM8 14.563v4.438c0 0.009-0.004 0.126 0.313 0.375s0.883 0.565 1.625 0.813c1.484 0.495 3.667 0.813 6.063 0.813s4.579-0.318 6.063-0.813c0.742-0.247 1.309-0.563 1.625-0.813s0.313-0.366 0.313-0.375v-4.438l-7.688 2.563-0.313 0.094-0.313-0.094z"></path>
</svg>
<!-- Generated by IcoMoon.io --><svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><title>graduation-cap</title><path d="M16 6.781l0.313 0.094 15.344 5.125-2.844 0.938-2.813 0.938v5.125c0 0.82-0.499 1.5-1.094 1.969s-1.332 0.798-2.219 1.094c-1.773 0.591-4.112 0.938-6.688 0.938s-4.914-0.346-6.688-0.938c-0.887-0.296-1.624-0.625-2.219-1.094s-1.094-1.149-1.094-1.969v-5.125l-2-0.656v8.063c0.597 0.346 1 0.979 1 1.719 0 1.105-0.895 2-2 2s-2-0.895-2-2c0-0.74 0.403-1.373 1-1.719v-8.75l-1.656-0.531 2.844-0.938 12.5-4.188zM16 8.875l-9.375 3.125 9.375 3.125 9.375-3.125zM8 14.563v4.438c0 0.009-0.004 0.126 0.313 0.375s0.883 0.565 1.625 0.813c1.484 0.495 3.667 0.813 6.063 0.813s4.579-0.318 6.063-0.813c0.742-0.247 1.309-0.563 1.625-0.813s0.313-0.366 0.313-0.375v-4.438l-7.688 2.563-0.313 0.094-0.313-0.094z"></path></svg>

Before

Width:  |  Height:  |  Size: 865 B

After

Width:  |  Height:  |  Size: 861 B

View File

@ -1,5 +0,0 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<title>hand-pointer-o</title>
<path d="M13 2c1.645 0 3 1.355 3 3v4.188c0.316-0.114 0.647-0.188 1-0.188 0.767 0 1.467 0.3 2 0.781 0.533-0.481 1.233-0.781 2-0.781 1.395 0 2.578 0.982 2.906 2.281 0.368-0.163 0.762-0.281 1.188-0.281 1.645 0 3 1.355 3 3v7.813c0 4.533-3.654 8.188-8.188 8.188h-1.719c-1.935 0-3.651-0.675-5-1.688l-0.031-0.063-0.063-0.031-8.188-8.094v-0.031c-1.154-1.154-1.154-3.034 0-4.188s3.034-1.154 4.188 0l0.25 0.219 0.656 0.688v-11.813c0-1.645 1.355-3 3-3zM13 4c-0.555 0-1 0.445-1 1v16.625l-4.313-4.313c-0.446-0.446-0.929-0.446-1.375 0s-0.446 0.929 0 1.375l8.094 8c1.051 0.788 2.317 1.313 3.781 1.313h1.719c3.467 0 6.188-2.721 6.188-6.188v-7.813c0-0.555-0.445-1-1-1s-1 0.445-1 1v2h-2.094v-4c0-0.555-0.445-1-1-1s-1 0.445-1 1v4h-2v-4c0-0.555-0.445-1-1-1s-1 0.445-1 1v4h-2v-11c0-0.555-0.445-1-1-1z"></path>
</svg>

Before

Width:  |  Height:  |  Size: 957 B

View File

@ -1,7 +1 @@
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" width="32px" height="32px" viewBox="0 0 32 32">
<path d="M26.1,20.7c-2.9,5.1-9.3,8.8-10.8,9.6c-2.1-1.1-13.7-7.8-13.7-16.1c0-3.6,2.8-6.5,6.5-6.5c2.6,0,4.9,1.5,5.9,3.9l0.7,1.7
l0.7-1.7c1-2.4,3.3-3.9,5.9-3.9c3.6,0,6.5,2.8,6.5,6.5V15h1.5v-0.8c0-4.5-3.5-8-8-8c-2.7,0-5.2,1.3-6.6,3.5
c-1.4-2.2-3.9-3.5-6.6-3.5c-4.5,0-8,3.5-8,8c0,10,14.3,17.3,14.9,17.6l0.3,0.2l0.3-0.2c0.3-0.2,8.3-4.2,11.8-10.4l0.4-0.7L26.5,20
L26.1,20.7z"/>
<polygon points="22.9,17 19.5,21.2 17,14.5 11.6,19.9 12.6,20.9 16.4,17.2 19,24.2 23.6,18.5 31.9,18.5 31.9,17 "/>
</svg>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" width="32px" height="32px" viewBox="0 0 32 32"><path d="M26.1,20.7c-2.9,5.1-9.3,8.8-10.8,9.6c-2.1-1.1-13.7-7.8-13.7-16.1c0-3.6,2.8-6.5,6.5-6.5c2.6,0,4.9,1.5,5.9,3.9l0.7,1.7 l0.7-1.7c1-2.4,3.3-3.9,5.9-3.9c3.6,0,6.5,2.8,6.5,6.5V15h1.5v-0.8c0-4.5-3.5-8-8-8c-2.7,0-5.2,1.3-6.6,3.5 c-1.4-2.2-3.9-3.5-6.6-3.5c-4.5,0-8,3.5-8,8c0,10,14.3,17.3,14.9,17.6l0.3,0.2l0.3-0.2c0.3-0.2,8.3-4.2,11.8-10.4l0.4-0.7L26.5,20 L26.1,20.7z"/><polygon points="22.9,17 19.5,21.2 17,14.5 11.6,19.9 12.6,20.9 16.4,17.2 19,24.2 23.6,18.5 31.9,18.5 31.9,17 "/></svg>

Before

Width:  |  Height:  |  Size: 625 B

After

Width:  |  Height:  |  Size: 606 B

View File

@ -1,5 +0,0 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<title>heart-o</title>
<path d="M9.5 5c3.433 0 5.645 2.066 6.5 2.938 0.855-0.871 3.067-2.938 6.5-2.938 4.138 0 7.5 3.404 7.5 7.5 0 2.857-2.469 5.031-2.469 5.031l-11.531 11.563-0.719-0.719-10.813-10.844s-0.619-0.573-1.219-1.469-1.25-2.134-1.25-3.563c0-4.096 3.362-7.5 7.5-7.5zM9.5 7c-3.042 0-5.5 2.496-5.5 5.5 0 0.772 0.423 1.716 0.906 2.438s0.969 1.188 0.969 1.188l10.125 10.125 10.125-10.125s1.875-2.080 1.875-3.625c0-3.004-2.458-5.5-5.5-5.5-2.986 0-5.75 2.906-5.75 2.906l-0.75 0.844-0.75-0.844s-2.764-2.906-5.75-2.906z"></path>
</svg>

Before

Width:  |  Height:  |  Size: 668 B

View File

@ -1,5 +1 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<title>location-arrow</title>
<path d="M16 4.438l0.906 2.188 8 19 0.906 2.125-2.156-0.813-7.656-2.875-9.813 3.688 0.906-2.125 8-19zM16 9.531l-6.188 14.719 6.188-2.313 0.344 0.125 5.844 2.188z"></path>
</svg>
<!-- Generated by IcoMoon.io --><svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><title>location-arrow</title><path d="M16 4.438l0.906 2.188 8 19 0.906 2.125-2.156-0.813-7.656-2.875-9.813 3.688 0.906-2.125 8-19zM16 9.531l-6.188 14.719 6.188-2.313 0.344 0.125 5.844 2.188z"></path></svg>

Before

Width:  |  Height:  |  Size: 339 B

After

Width:  |  Height:  |  Size: 335 B

View File

@ -1,7 +1 @@
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" width="32px" height="32px" viewBox="0 0 32 32">
<path d="M31.7,29.2L29.8,23V7.1c0-1.1-1-2.1-2.1-2.1H4.8c-1.1,0-2.1,1-2.1,2.1V23l-2,6.1c-0.2,0.6-0.1,1.3,0.2,1.9
c0.4,0.6,1,0.9,1.7,0.9h27.1c0.7,0,1.3-0.3,1.7-0.9C31.8,30.4,31.9,29.7,31.7,29.2z M4.2,7.1c0-0.3,0.3-0.6,0.6-0.6h22.8
c0.3,0,0.6,0.3,0.6,0.6v15.3h-24V7.1z M30.2,30.2c-0.1,0.1-0.2,0.2-0.5,0.2H2.6c-0.3,0-0.4-0.2-0.5-0.2C2.1,30,2,29.8,2.1,29.6
L4,23.9h24.4l1.8,5.8C30.4,29.8,30.3,30,30.2,30.2z"/>
<rect x="13.5" y="27.8" width="5.6" height="1.5"/>
</svg>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" width="32px" height="32px" viewBox="0 0 32 32"><path d="M31.7,29.2L29.8,23V7.1c0-1.1-1-2.1-2.1-2.1H4.8c-1.1,0-2.1,1-2.1,2.1V23l-2,6.1c-0.2,0.6-0.1,1.3,0.2,1.9 c0.4,0.6,1,0.9,1.7,0.9h27.1c0.7,0,1.3-0.3,1.7-0.9C31.8,30.4,31.9,29.7,31.7,29.2z M4.2,7.1c0-0.3,0.3-0.6,0.6-0.6h22.8 c0.3,0,0.6,0.3,0.6,0.6v15.3h-24V7.1z M30.2,30.2c-0.1,0.1-0.2,0.2-0.5,0.2H2.6c-0.3,0-0.4-0.2-0.5-0.2C2.1,30,2,29.8,2.1,29.6 L4,23.9h24.4l1.8,5.8C30.4,29.8,30.3,30,30.2,30.2z"/><rect x="13.5" y="27.8" width="5.6" height="1.5"/></svg>

Before

Width:  |  Height:  |  Size: 596 B

After

Width:  |  Height:  |  Size: 578 B

Some files were not shown because too many files have changed in this diff Show More