├── .prettierignore
├── .gitignore
├── .tool-versions
├── examples
├── sveltekit-app
│ ├── .npmrc
│ ├── src
│ │ ├── lib
│ │ │ └── index.ts
│ │ ├── app.d.ts
│ │ ├── app.html
│ │ └── routes
│ │ │ └── +page.svelte
│ ├── static
│ │ └── favicon.png
│ ├── vite.config.ts
│ ├── .gitignore
│ ├── .eslintignore
│ ├── tsconfig.json
│ ├── .eslintrc.cjs
│ ├── svelte.config.js
│ ├── README.md
│ └── package.json
├── svelte-app
│ ├── .vscode
│ │ └── extensions.json
│ ├── src
│ │ ├── app.css
│ │ ├── vite-env.d.ts
│ │ ├── main.js
│ │ └── App.svelte
│ ├── vite.config.js
│ ├── .gitignore
│ ├── index.html
│ ├── package.json
│ ├── jsconfig.json
│ ├── public
│ │ └── vite.svg
│ ├── README.md
│ └── package-lock.json
└── svelte-app-typescript
│ ├── .vscode
│ └── extensions.json
│ ├── src
│ ├── vite-env.d.ts
│ ├── app.css
│ ├── main.ts
│ └── App.svelte
│ ├── tsconfig.node.json
│ ├── vite.config.ts
│ ├── svelte.config.js
│ ├── .gitignore
│ ├── index.html
│ ├── tsconfig.json
│ ├── package.json
│ ├── public
│ └── vite.svg
│ └── README.md
├── babel.config.cjs
├── .prettierrc.js
├── src
├── __mocks__
│ └── logger.js
├── index.js
├── test-setup.js
├── logger.js
├── utils
│ ├── object-with-key.js
│ ├── __tests__
│ │ ├── camelize.test.js
│ │ ├── object-with-key.test.js
│ │ ├── normalize-icon-args.test.js
│ │ └── get-class-list-from-props.test.js
│ ├── camelize.js
│ ├── normalize-icon-args.js
│ └── get-class-list-from-props.js
├── components
│ ├── SvgElement.svelte
│ ├── __fixtures__
│ │ ├── icons.js
│ │ └── helpers.js
│ ├── FontAwesomeIcon.svelte
│ └── __tests__
│ │ └── FontAwesomeIcon.test.js
└── converter.js
├── .claude
└── settings.local.json
├── vitest.config.js
├── UPGRADING.md
├── .github
├── ISSUE_TEMPLATE
│ ├── feature_request.md
│ └── bug_report.md
└── workflows
│ └── ci.yml
├── rollup.config.js
├── LICENSE.txt
├── .eslintrc.json
├── CHANGELOG.md
├── index.d.ts
├── DEVELOPMENT.md
├── CONTRIBUTING.md
├── README.md
├── CODE_OF_CONDUCT.md
├── package.json
├── index.es.js
└── index.js
/.prettierignore:
--------------------------------------------------------------------------------
1 | /index.*
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .DS_Store
3 |
--------------------------------------------------------------------------------
/.tool-versions:
--------------------------------------------------------------------------------
1 | nodejs 22.14.0
2 | python 3.10.1
3 |
--------------------------------------------------------------------------------
/examples/sveltekit-app/.npmrc:
--------------------------------------------------------------------------------
1 | engine-strict=true
2 |
--------------------------------------------------------------------------------
/babel.config.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: ['@babel/preset-env']
3 | }
4 |
--------------------------------------------------------------------------------
/.prettierrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | semi: false,
3 | singleQuote: true
4 | }
5 |
--------------------------------------------------------------------------------
/src/__mocks__/logger.js:
--------------------------------------------------------------------------------
1 | import { vi } from 'vitest'
2 |
3 | export default vi.fn()
4 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | export { default as FontAwesomeIcon } from './components/FontAwesomeIcon.svelte'
2 |
--------------------------------------------------------------------------------
/src/test-setup.js:
--------------------------------------------------------------------------------
1 | import '@testing-library/jest-dom'
2 |
3 | // Global test setup for vitest
4 |
--------------------------------------------------------------------------------
/examples/svelte-app/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": ["svelte.svelte-vscode"]
3 | }
4 |
--------------------------------------------------------------------------------
/examples/svelte-app-typescript/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": ["svelte.svelte-vscode"]
3 | }
4 |
--------------------------------------------------------------------------------
/examples/svelte-app/src/app.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | padding: 0;
4 | font-family: sans-serif;
5 | }
6 |
--------------------------------------------------------------------------------
/examples/svelte-app/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
--------------------------------------------------------------------------------
/examples/sveltekit-app/src/lib/index.ts:
--------------------------------------------------------------------------------
1 | // place files you want to import through the `$lib` alias in this folder.
2 |
--------------------------------------------------------------------------------
/examples/svelte-app-typescript/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
--------------------------------------------------------------------------------
/examples/sveltekit-app/static/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FortAwesome/svelte-fontawesome/HEAD/examples/sveltekit-app/static/favicon.png
--------------------------------------------------------------------------------
/examples/sveltekit-app/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { sveltekit } from '@sveltejs/kit/vite';
2 | import { defineConfig } from 'vite';
3 |
4 | export default defineConfig({
5 | plugins: [sveltekit()]
6 | });
7 |
--------------------------------------------------------------------------------
/examples/sveltekit-app/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /build
4 | /.svelte-kit
5 | /package
6 | .env
7 | .env.*
8 | !.env.example
9 | vite.config.js.timestamp-*
10 | vite.config.ts.timestamp-*
11 |
--------------------------------------------------------------------------------
/examples/svelte-app-typescript/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "module": "ESNext",
5 | "moduleResolution": "node"
6 | },
7 | "include": ["vite.config.ts"]
8 | }
9 |
--------------------------------------------------------------------------------
/examples/svelte-app/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import { svelte } from '@sveltejs/vite-plugin-svelte'
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [svelte()]
7 | })
8 |
--------------------------------------------------------------------------------
/examples/svelte-app-typescript/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import { svelte } from '@sveltejs/vite-plugin-svelte'
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [svelte()]
7 | })
8 |
--------------------------------------------------------------------------------
/examples/sveltekit-app/.eslintignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /build
4 | /.svelte-kit
5 | /package
6 | .env
7 | .env.*
8 | !.env.example
9 |
10 | # Ignore files for PNPM, NPM and YARN
11 | pnpm-lock.yaml
12 | package-lock.json
13 | yarn.lock
14 |
--------------------------------------------------------------------------------
/examples/svelte-app-typescript/svelte.config.js:
--------------------------------------------------------------------------------
1 | import sveltePreprocess from 'svelte-preprocess'
2 |
3 | export default {
4 | // Consult https://github.com/sveltejs/svelte-preprocess
5 | // for more information about preprocessors
6 | preprocess: sveltePreprocess()
7 | }
8 |
--------------------------------------------------------------------------------
/src/logger.js:
--------------------------------------------------------------------------------
1 | let PRODUCTION = false
2 |
3 | try {
4 | PRODUCTION = process.env.NODE_ENV === 'production'
5 | } catch (e) {}
6 |
7 | export default function(...args) {
8 | if (!PRODUCTION && console && typeof console.error === 'function') {
9 | console.error(...args)
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/.claude/settings.local.json:
--------------------------------------------------------------------------------
1 | {
2 | "permissions": {
3 | "allow": [
4 | "Bash(npm uninstall:*)",
5 | "Bash(npm test)",
6 | "Bash(npm install:*)",
7 | "Bash(node:*)",
8 | "Bash(npm info:*)",
9 | "Bash(npm run lint)",
10 | "Bash(npm run lint:*)"
11 | ],
12 | "deny": [],
13 | "ask": []
14 | }
15 | }
--------------------------------------------------------------------------------
/examples/sveltekit-app/src/app.d.ts:
--------------------------------------------------------------------------------
1 | // See https://kit.svelte.dev/docs/types#app
2 | // for information about these interfaces
3 | declare global {
4 | namespace App {
5 | // interface Error {}
6 | // interface Locals {}
7 | // interface PageData {}
8 | // interface PageState {}
9 | // interface Platform {}
10 | }
11 | }
12 |
13 | export {};
14 |
--------------------------------------------------------------------------------
/vitest.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vitest/config'
2 | import { svelte } from '@sveltejs/vite-plugin-svelte'
3 |
4 | export default defineConfig({
5 | plugins: [svelte({ hot: false })],
6 | test: {
7 | environment: 'jsdom',
8 | setupFiles: ['./src/test-setup.js'],
9 | include: ['src/**/*.test.js'],
10 | globals: true
11 | }
12 | })
--------------------------------------------------------------------------------
/UPGRADING.md:
--------------------------------------------------------------------------------
1 | # Upgrading Guide
2 |
3 | See the [CHANGELOG.md](./CHANGELOG.md) for detailed information about what has changed between versions.
4 |
5 | This guide is useful to figure out what you need to do between breaking changes.
6 |
7 | As always, [submit issues](https://github.com/FortAwesome/svelte-fontawesome/issues/new) that you run into with this guide or with these upgrades to us.
8 |
9 |
--------------------------------------------------------------------------------
/examples/svelte-app/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
--------------------------------------------------------------------------------
/examples/svelte-app-typescript/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
--------------------------------------------------------------------------------
/examples/sveltekit-app/src/app.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | %sveltekit.head%
8 |
9 |
10 | %sveltekit.body%
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/utils/object-with-key.js:
--------------------------------------------------------------------------------
1 | // creates an object with a key of key
2 | // and a value of value
3 | // if certain conditions are met
4 | export default function objectWithKey(key, value) {
5 | // if the value is a non-empty array
6 | // or it's not an array but it is truthy
7 | // then create the object with the key and the value
8 | // if not, return an empty array
9 | return (Array.isArray(value) && value.length > 0) ||
10 | (!Array.isArray(value) && value)
11 | ? { [key]: value }
12 | : {}
13 | }
14 |
--------------------------------------------------------------------------------
/examples/svelte-app/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | svelte-app example
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/examples/svelte-app-typescript/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | svelte-app-typescript example
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/examples/sveltekit-app/src/routes/+page.svelte:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 | Hello SvelteKit
13 |
14 |
15 |
--------------------------------------------------------------------------------
/examples/svelte-app/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "svelte-app",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "vite build",
9 | "preview": "vite preview"
10 | },
11 | "devDependencies": {
12 | "@fortawesome/fontawesome-svg-core": "^7.0.0",
13 | "@fortawesome/free-brands-svg-icons": "^7.0.0",
14 | "@fortawesome/free-solid-svg-icons": "^7.0.0",
15 | "@fortawesome/svelte-fontawesome": "^0.2.0",
16 | "@sveltejs/vite-plugin-svelte": "^1.0.1",
17 | "svelte": "^3.49.0",
18 | "vite": "^3.0.0"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/examples/svelte-app/src/main.js:
--------------------------------------------------------------------------------
1 | import './app.css'
2 | import App from './App.svelte'
3 |
4 | import { library } from '@fortawesome/fontawesome-svg-core'
5 | import { fab } from '@fortawesome/free-brands-svg-icons'
6 | import {
7 | faCoffee,
8 | faCog,
9 | faSpinner,
10 | faQuoteLeft,
11 | faSquare,
12 | faCheckSquare
13 | } from '@fortawesome/free-solid-svg-icons'
14 |
15 | library.add(
16 | fab,
17 | faCoffee,
18 | faCog,
19 | faSpinner,
20 | faQuoteLeft,
21 | faSquare,
22 | faCheckSquare
23 | )
24 |
25 | const app = new App({
26 | target: document.getElementById('app')
27 | })
28 |
29 | export default app
30 |
--------------------------------------------------------------------------------
/examples/svelte-app-typescript/src/app.css:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | }
4 |
5 | .App-logo {
6 | animation: App-logo-spin infinite 20s linear;
7 | height: 40vmin;
8 | }
9 |
10 | .App-header {
11 | background-color: #282c34;
12 | min-height: 100vh;
13 | display: flex;
14 | flex-direction: column;
15 | align-items: center;
16 | justify-content: center;
17 | font-size: calc(10px + 2vmin);
18 | color: white;
19 | }
20 |
21 | .App-link {
22 | color: #61dafb;
23 | }
24 |
25 | @keyframes App-logo-spin {
26 | from {
27 | transform: rotate(0deg);
28 | }
29 | to {
30 | transform: rotate(360deg);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/utils/__tests__/camelize.test.js:
--------------------------------------------------------------------------------
1 | import camelize from '../camelize'
2 |
3 | describe('camelize', () => {
4 | test('numerical values return same value', () => {
5 | const numerical = 999
6 | expect(camelize(numerical)).toBe(numerical)
7 | })
8 |
9 | test('first char is always lowercase', () => {
10 | expect(camelize('f-a')).toBe('fA')
11 | expect(camelize('F-a')).toBe('fA')
12 | })
13 |
14 | test('multiple humps', () => {
15 | expect(camelize('fa-coffee')).toBe('faCoffee')
16 | expect(camelize('fa-fake-icon')).toBe('faFakeIcon')
17 | expect(camelize('fa-fake-icon-longer')).toBe('faFakeIconLonger')
18 | })
19 | })
20 |
--------------------------------------------------------------------------------
/examples/sveltekit-app/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./.svelte-kit/tsconfig.json",
3 | "compilerOptions": {
4 | "allowJs": true,
5 | "checkJs": true,
6 | "esModuleInterop": true,
7 | "forceConsistentCasingInFileNames": true,
8 | "resolveJsonModule": true,
9 | "skipLibCheck": true,
10 | "sourceMap": true,
11 | "strict": true,
12 | "moduleResolution": "bundler"
13 | }
14 | // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias
15 | //
16 | // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
17 | // from the referenced tsconfig.json - TypeScript does not merge them in
18 | }
19 |
--------------------------------------------------------------------------------
/examples/svelte-app-typescript/src/main.ts:
--------------------------------------------------------------------------------
1 | import './app.css'
2 | import App from './App.svelte'
3 |
4 | // Importing types from the API library along with other exports
5 | import {
6 | library
7 | } from '@fortawesome/fontawesome-svg-core'
8 | import { fab } from '@fortawesome/free-brands-svg-icons'
9 | import {
10 | faCog,
11 | faSpinner,
12 | faQuoteLeft,
13 | faSquare,
14 | faCheckSquare
15 | } from '@fortawesome/free-solid-svg-icons'
16 |
17 | library.add(
18 | fab,
19 | faCog,
20 | faSpinner,
21 | faQuoteLeft,
22 | faSquare,
23 | faCheckSquare
24 | )
25 |
26 | const app = new App({
27 | target: document.getElementById('app')
28 | })
29 |
30 | export default app
31 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 | ---
8 |
9 | **Is your feature request related to a problem? Please describe.**
10 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
11 |
12 | **Describe the solution you'd like**
13 | A clear and concise description of what you want to happen.
14 |
15 | **Describe alternatives you've considered**
16 | A clear and concise description of any alternative solutions or features you've considered.
17 |
18 | **Additional context**
19 | Add any other context or screenshots about the feature request here.
20 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 | ---
8 |
9 | **Describe the bug**
10 | A clear and concise description of what the bug is.
11 |
12 | **Reproducible test case**
13 | Include a URL (codepen.io, jsfiddle.net, Git repository, codesandbox.io, stackblitz.com, etc.) that demonstrates the problem.
14 |
15 | **Expected behavior**
16 | A clear and concise description of what you expected to happen.
17 |
18 | **Desktop (please complete the following information):**
19 |
20 | - Browser [e.g. chrome, safari]
21 | - Version
22 |
23 | **Additional context**
24 | Add any other context about the problem here.
25 |
--------------------------------------------------------------------------------
/examples/sveltekit-app/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | /** @type { import("eslint").Linter.Config } */
2 | module.exports = {
3 | root: true,
4 | extends: [
5 | 'eslint:recommended',
6 | 'plugin:@typescript-eslint/recommended',
7 | 'plugin:svelte/recommended'
8 | ],
9 | parser: '@typescript-eslint/parser',
10 | plugins: ['@typescript-eslint'],
11 | parserOptions: {
12 | sourceType: 'module',
13 | ecmaVersion: 2020,
14 | extraFileExtensions: ['.svelte']
15 | },
16 | env: {
17 | browser: true,
18 | es2017: true,
19 | node: true
20 | },
21 | overrides: [
22 | {
23 | files: ['*.svelte'],
24 | parser: 'svelte-eslint-parser',
25 | parserOptions: {
26 | parser: '@typescript-eslint/parser'
27 | }
28 | }
29 | ]
30 | };
31 |
--------------------------------------------------------------------------------
/src/utils/camelize.js:
--------------------------------------------------------------------------------
1 | // Camelize taken from humps
2 | // humps is copyright © 2012+ Dom Christie
3 | // Released under the MIT license.
4 |
5 | // Performant way to determine if object coerces to a number
6 | function _isNumerical(obj) {
7 | obj = obj - 0
8 |
9 | // eslint-disable-next-line no-self-compare
10 | return obj === obj
11 | }
12 |
13 | export default function camelize(string) {
14 | if (_isNumerical(string)) {
15 | return string
16 | }
17 |
18 | // eslint-disable-next-line no-useless-escape
19 | string = string.replace(/[\-_\s]+(.)?/g, function(match, chr) {
20 | return chr ? chr.toUpperCase() : ''
21 | })
22 |
23 | // Ensure 1st char is always lowercase
24 | return string.substr(0, 1).toLowerCase() + string.substr(1)
25 | }
26 |
--------------------------------------------------------------------------------
/examples/svelte-app-typescript/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@tsconfig/svelte/tsconfig.json",
3 | "compilerOptions": {
4 | "target": "ESNext",
5 | "useDefineForClassFields": true,
6 | "module": "ESNext",
7 | "resolveJsonModule": true,
8 | "baseUrl": ".",
9 | /**
10 | * Typecheck JS in `.svelte` and `.js` files by default.
11 | * Disable checkJs if you'd like to use dynamic types in JS.
12 | * Note that setting allowJs false does not prevent the use
13 | * of JS in `.svelte` files.
14 | */
15 | "allowJs": true,
16 | "checkJs": true,
17 | "isolatedModules": true
18 | },
19 | "include": ["src/**/*.d.ts", "src/**/*.ts", "src/**/*.js", "src/**/*.svelte"],
20 | "references": [{ "path": "./tsconfig.node.json" }]
21 | }
22 |
--------------------------------------------------------------------------------
/examples/sveltekit-app/svelte.config.js:
--------------------------------------------------------------------------------
1 | import adapter from '@sveltejs/adapter-auto';
2 | import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
3 |
4 | /** @type {import('@sveltejs/kit').Config} */
5 | const config = {
6 | // Consult https://kit.svelte.dev/docs/integrations#preprocessors
7 | // for more information about preprocessors
8 | preprocess: vitePreprocess(),
9 |
10 | kit: {
11 | // adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list.
12 | // If your environment is not supported or you settled on a specific environment, switch out the adapter.
13 | // See https://kit.svelte.dev/docs/adapters for more information about adapters.
14 | adapter: adapter()
15 | }
16 | };
17 |
18 | export default config;
19 |
--------------------------------------------------------------------------------
/src/utils/__tests__/object-with-key.test.js:
--------------------------------------------------------------------------------
1 | import objectWithKey from '../object-with-key'
2 |
3 | describe('object with key', () => {
4 | const KEY = 'my-key'
5 |
6 | test('value is array length greater than 1', () => {
7 | const VALUE = [1]
8 | expect(objectWithKey(KEY, [1])).toStrictEqual({
9 | [KEY]: VALUE
10 | })
11 | })
12 |
13 | test('value array empty', () => {
14 | expect(objectWithKey(KEY, [])).toStrictEqual({})
15 | })
16 |
17 | test('value is not array', () => {
18 | const VALUE = 'value'
19 | expect(objectWithKey(KEY, VALUE)).toStrictEqual({
20 | [KEY]: VALUE
21 | })
22 | })
23 |
24 | test('value not truthy', () => {
25 | expect(objectWithKey(KEY)).toStrictEqual({})
26 | expect(objectWithKey(KEY, null)).toStrictEqual({})
27 | })
28 | })
29 |
--------------------------------------------------------------------------------
/examples/svelte-app-typescript/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "svelte-app-typescript",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "vite build",
9 | "preview": "vite preview",
10 | "check": "svelte-check --tsconfig ./tsconfig.json"
11 | },
12 | "devDependencies": {
13 | "@fortawesome/fontawesome-svg-core": "^7.0.0",
14 | "@fortawesome/free-brands-svg-icons": "^7.0.0",
15 | "@fortawesome/free-solid-svg-icons": "^7.0.0",
16 | "@fortawesome/svelte-fontawesome": "^0.2.0",
17 | "@sveltejs/vite-plugin-svelte": "^1.0.1",
18 | "@tsconfig/svelte": "^3.0.0",
19 | "svelte": "^3.49.0",
20 | "svelte-check": "^2.8.0",
21 | "svelte-preprocess": "^4.10.7",
22 | "tslib": "^2.4.0",
23 | "typescript": "^4.6.4",
24 | "vite": "^3.0.0"
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/utils/__tests__/normalize-icon-args.test.js:
--------------------------------------------------------------------------------
1 | import normalizeIconArgs from '../normalize-icon-args'
2 |
3 | describe('normalize icon args', () => {
4 | const PREFIX = 'far'
5 | const NAME = 'circle'
6 |
7 | test('handle null', () => {
8 | expect(normalizeIconArgs(null)).toBeNull()
9 | })
10 |
11 | test('handle object', () => {
12 | const icon = {
13 | prefix: 'far',
14 | iconName: 'circle'
15 | }
16 | expect(normalizeIconArgs(icon)).toStrictEqual(icon)
17 | })
18 |
19 | test('handle array', () => {
20 | const icon = [PREFIX, NAME]
21 | expect(normalizeIconArgs(icon)).toStrictEqual({
22 | prefix: PREFIX,
23 | iconName: NAME
24 | })
25 | })
26 |
27 | test('handle string', () => {
28 | const DEFAULT_PREFIX = 'fas'
29 | expect(normalizeIconArgs(NAME)).toStrictEqual({
30 | prefix: DEFAULT_PREFIX,
31 | iconName: NAME
32 | })
33 | })
34 | })
35 |
--------------------------------------------------------------------------------
/rollup.config.js:
--------------------------------------------------------------------------------
1 | import resolve from '@rollup/plugin-node-resolve'
2 | import commonJs from '@rollup/plugin-commonjs'
3 | import svelte from 'rollup-plugin-svelte'
4 |
5 | const name = 'svelte-fontawesome'
6 | const globals = {
7 | '@fortawesome/fontawesome-svg-core': 'FontAwesome'
8 | }
9 |
10 | export default {
11 | external: ['@fortawesome/fontawesome-svg-core'],
12 | input: 'src/index.js',
13 | output: [
14 | {
15 | name,
16 | globals,
17 | format: 'umd',
18 | file: 'index.js',
19 | },
20 | {
21 | name,
22 | globals,
23 | format: 'es',
24 | file: 'index.es.js',
25 | },
26 | ],
27 | plugins: [
28 | resolve({
29 | jsnext: true,
30 | main: true,
31 | }),
32 | commonJs(),
33 | svelte({
34 | exclude: 'node_modules/**',
35 | compilerOptions: {
36 | generate: 'ssr',
37 | hydratable: true
38 | }
39 | }),
40 | ],
41 | }
42 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on: [push, pull_request]
4 |
5 | jobs:
6 | build:
7 | runs-on: ubuntu-latest
8 |
9 | strategy:
10 | matrix:
11 | node: [22]
12 | svelte: [3.x, 4.x, 5.x]
13 | fontawesome:
14 | - { core: 7.x, icons: 5.x }
15 | - { core: 6.x, icons: 6.x }
16 | - { core: 7.x, icons: 7.x }
17 |
18 | steps:
19 | - uses: actions/checkout@v1
20 | - uses: actions/setup-node@v1
21 | with:
22 | node-version: ${{ matrix.node }}
23 | - name: npm install, build, and test
24 | run: |
25 | npm install
26 | npm run build
27 | npm install --no-save svelte@${{ matrix.svelte }}
28 | npm install --force --no-save @fortawesome/fontawesome-svg-core@${{ matrix.fontawesome.core }} @fortawesome/free-solid-svg-icons@${{ matrix.fontawesome.icons }}
29 | npm run lint
30 | npm run test
31 | - name: dist
32 | run: |
33 | npm run dist
34 |
--------------------------------------------------------------------------------
/src/components/SvgElement.svelte:
--------------------------------------------------------------------------------
1 |
32 |
33 |
34 | {@html markup}
35 |
36 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright 2018 Fonticons, Inc.
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of
4 | this software and associated documentation files (the "Software"), to deal in
5 | the Software without restriction, including without limitation the rights to
6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7 | of the Software, and to permit persons to whom the Software is furnished to do
8 | so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all
11 | copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | SOFTWARE.
20 |
--------------------------------------------------------------------------------
/examples/sveltekit-app/README.md:
--------------------------------------------------------------------------------
1 | # create-svelte
2 |
3 | Everything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/main/packages/create-svelte).
4 |
5 | ## Creating a project
6 |
7 | If you're seeing this, you've probably already done this step. Congrats!
8 |
9 | ```bash
10 | # create a new project in the current directory
11 | npm create svelte@latest
12 |
13 | # create a new project in my-app
14 | npm create svelte@latest my-app
15 | ```
16 |
17 | ## Developing
18 |
19 | Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
20 |
21 | ```bash
22 | npm run dev
23 |
24 | # or start the server and open the app in a new browser tab
25 | npm run dev -- --open
26 | ```
27 |
28 | ## Building
29 |
30 | To create a production version of your app:
31 |
32 | ```bash
33 | npm run build
34 | ```
35 |
36 | You can preview the production build with `npm run preview`.
37 |
38 | > To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment.
39 |
--------------------------------------------------------------------------------
/examples/sveltekit-app/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sveltekit-app",
3 | "version": "0.0.1",
4 | "private": true,
5 | "scripts": {
6 | "dev": "vite dev",
7 | "build": "vite build",
8 | "preview": "vite preview",
9 | "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
10 | "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
11 | "lint": "eslint ."
12 | },
13 | "devDependencies": {
14 | "@fortawesome/fontawesome-svg-core": "^7.0.0",
15 | "@fortawesome/free-solid-svg-icons": "^7.0.0",
16 | "@fortawesome/svelte-fontawesome": "^0.2.0",
17 | "@sveltejs/adapter-auto": "^3.0.0",
18 | "@sveltejs/kit": "^2.0.0",
19 | "@sveltejs/vite-plugin-svelte": "^3.0.0",
20 | "@types/eslint": "8.56.0",
21 | "@typescript-eslint/eslint-plugin": "^6.0.0",
22 | "@typescript-eslint/parser": "^6.0.0",
23 | "eslint": "^8.56.0",
24 | "eslint-plugin-svelte": "^2.35.1",
25 | "svelte": "^4.2.7",
26 | "svelte-check": "^3.6.0",
27 | "tslib": "^2.4.1",
28 | "typescript": "^5.0.0",
29 | "vite": "^5.0.3"
30 | },
31 | "type": "module"
32 | }
33 |
--------------------------------------------------------------------------------
/examples/svelte-app/jsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "moduleResolution": "Node",
4 | "target": "ESNext",
5 | "module": "ESNext",
6 | /**
7 | * svelte-preprocess cannot figure out whether you have
8 | * a value or a type, so tell TypeScript to enforce using
9 | * `import type` instead of `import` for Types.
10 | */
11 | "importsNotUsedAsValues": "error",
12 | "isolatedModules": true,
13 | "resolveJsonModule": true,
14 | /**
15 | * To have warnings / errors of the Svelte compiler at the
16 | * correct position, enable source maps by default.
17 | */
18 | "sourceMap": true,
19 | "esModuleInterop": true,
20 | "skipLibCheck": true,
21 | "forceConsistentCasingInFileNames": true,
22 | "baseUrl": ".",
23 | /**
24 | * Typecheck JS in `.svelte` and `.js` files by default.
25 | * Disable this if you'd like to use dynamic types.
26 | */
27 | "checkJs": true
28 | },
29 | /**
30 | * Use global.d.ts instead of compilerOptions.types
31 | * to avoid limiting type declarations.
32 | */
33 | "include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.svelte"]
34 | }
35 |
--------------------------------------------------------------------------------
/src/utils/normalize-icon-args.js:
--------------------------------------------------------------------------------
1 | import { parse as faParse } from '@fortawesome/fontawesome-svg-core'
2 |
3 | // Normalize icon arguments
4 | export default function normalizeIconArgs(icon) {
5 | // this has everything that it needs to be rendered which means it was probably imported
6 | // directly from an icon svg package
7 | if (icon && typeof icon === 'object' && icon.prefix && icon.iconName && icon.icon) {
8 | return icon
9 | }
10 |
11 | if (faParse.icon) {
12 | return faParse.icon(icon)
13 | }
14 |
15 | // if the icon is null, there's nothing to do
16 | if (icon === null) {
17 | return null
18 | }
19 |
20 | // if the icon is an object and has a prefix and an icon name, return it
21 | if (icon && typeof icon === 'object' && icon.prefix && icon.iconName) {
22 | return icon
23 | }
24 |
25 | // if it's an array with length of two
26 | if (Array.isArray(icon) && icon.length === 2) {
27 | // use the first item as prefix, second as icon name
28 | return { prefix: icon[0], iconName: icon[1] }
29 | }
30 |
31 | // if it's a string, use it as the icon name
32 | if (typeof icon === 'string') {
33 | return { prefix: 'fas', iconName: icon }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/components/__fixtures__/icons.js:
--------------------------------------------------------------------------------
1 | export const faCoffee = {
2 | prefix: 'fas',
3 | iconName: 'coffee',
4 | icon: [
5 | 640,
6 | 512,
7 | [],
8 | 'f0f4',
9 | 'M192 384h192c53 0 96-43 96-96h32c70.6 0 128-57.4 128-128S582.6 32 512 32H120c-13.3 0-24 10.7-24 24v232c0 53 43 96 96 96zM512 96c35.3 0 64 28.7 64 64s-28.7 64-64 64h-32V96h32zm47.7 384H48.3c-47.6 0-61-64-36-64h583.3c25 0 11.8 64-35.9 64z'
10 | ]
11 | }
12 |
13 | export const faCircle = {
14 | prefix: 'fas',
15 | iconName: 'circle',
16 | icon: [
17 | 640,
18 | 512,
19 | [],
20 | 'f0f4',
21 | 'M192 384h192c53 0 96-43 96-96h32c70.6 0 128-57.4 128-128S582.6 32 512 32H120c-13.3 0-24 10.7-24 24v232c0 53 43 96 96 96zM512 96c35.3 0 64 28.7 64 64s-28.7 64-64 64h-32V96h32zm47.7 384H48.3c-47.6 0-61-64-36-64h583.3c25 0 11.8 64-35.9 64z'
22 | ]
23 | }
24 |
25 | export const faSpartan = {
26 | prefix: 'fat',
27 | iconName: 'spartan',
28 | icon: [
29 | 640,
30 | 512,
31 | [],
32 | 'f0f4',
33 | 'M192 384h192c53 0 96-43 96-96h32c70.6 0 128-57.4 128-128S582.6 32 512 32H120c-13.3 0-24 10.7-24 24v232c0 53 43 96 96 96zM512 96c35.3 0 64 28.7 64 64s-28.7 64-64 64h-32V96h32zm47.7 384H48.3c-47.6 0-61-64-36-64h583.3c25 0 11.8 64-35.9 64z'
34 | ]
35 | }
36 |
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "standard",
3 | "plugins": ["svelte3"],
4 | "rules": {
5 | "space-before-function-paren": 0
6 | },
7 | "env": {
8 | "node": true,
9 | "browser": true,
10 | "es2022": true
11 | },
12 | "parser": "@babel/eslint-parser",
13 | "parserOptions": {
14 | "ecmaVersion": 2022,
15 | "sourceType": "module",
16 | "requireConfigFile": false,
17 | "babelOptions": {
18 | "presets": ["@babel/preset-env"]
19 | }
20 | },
21 | "globals": {
22 | "test": "readonly",
23 | "describe": "readonly",
24 | "expect": "readonly",
25 | "beforeEach": "readonly",
26 | "afterEach": "readonly",
27 | "vi": "readonly"
28 | },
29 | "overrides": [
30 | {
31 | "files": ["*.svelte"],
32 | "processor": "svelte3/svelte3",
33 | "rules": {
34 | "import/first": "off",
35 | "import/no-duplicates": "off",
36 | "import/no-mutable-exports": "off",
37 | "import/no-unresolved": "off",
38 | "import/prefer-default-export": "off",
39 | "no-multiple-empty-lines": [
40 | "error",
41 | {
42 | "max": 1,
43 | "maxBOF": 2,
44 | "maxEOF": 0
45 | }
46 | ]
47 | }
48 |
49 | }
50 | ]
51 | }
52 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | All notable changes to this project will be documented in this file.
4 |
5 | The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/).
6 |
7 | ---
8 |
9 | ## [0.2.4](https://github.com/FortAwesome/svelte-fontawesome/releases/tag/0.2.4) - 2025-08-15
10 |
11 | ### Changed
12 |
13 | - Support for Font Awesome 7
14 | - Added explicit support and testing for Svelte 4 & 5
15 |
16 | ## [0.2.3](https://github.com/FortAwesome/svelte-fontawesome/releases/tag/0.2.3) - 2024-11-12
17 |
18 | ### Fixed
19 |
20 | - Color and style props can now be set as epected #11
21 |
22 | ## [0.2.2](https://github.com/FortAwesome/svelte-fontawesome/releases/tag/0.2.2) - 2024-02-16
23 |
24 | ### Fixed
25 |
26 | - Types are not recognized when using TypeScript #8
27 |
28 | ## [0.2.1](https://github.com/FortAwesome/svelte-fontawesome/releases/tag/0.2.1) - 2023-12-21
29 |
30 | ### Fixed
31 |
32 | - Support Sveltekit 2 by adding exports to package.json #6
33 |
34 | ## [0.2.0](https://github.com/FortAwesome/svelte-fontawesome/releases/tag/0.2.0) - 2022-08-02
35 |
36 | Special thanks to [@seantimm](https://github.com/seantimm) for putting the work in to port this to Svelte.
37 |
38 | ### Added
39 |
40 | * Initial release based largely on the @fortawesome/react-fontawesome component
41 |
--------------------------------------------------------------------------------
/examples/svelte-app/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/examples/svelte-app-typescript/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/index.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | import * as CSS from 'csstype';
3 | import { SvelteComponentTyped } from 'svelte';
4 | import {
5 | Transform,
6 | IconName,
7 | IconProp,
8 | FlipProp,
9 | SizeProp,
10 | PullProp,
11 | RotateProp,
12 | FaSymbol
13 | } from '@fortawesome/fontawesome-svg-core'
14 |
15 | export class FontAwesomeIcon extends SvelteComponentTyped {}
16 |
17 | // This is identical to the version of Omit in Typescript 3.5. It is included for compatibility with older versions of Typescript.
18 | type BackwardCompatibleOmit = Pick>;
19 |
20 | type WithPrefix = `fa-${T} fa-${IconName}`
21 |
22 | export interface FontAwesomeIconProps {
23 | icon: WithPrefix<'solid'> | WithPrefix<'regular'> | WithPrefix<'light'> | WithPrefix<'thin'> | WithPrefix<'duotone'> | WithPrefix<'brands'> | IconProp
24 | mask?: IconProp
25 | maskId?: string
26 | class?: string
27 | spin?: boolean
28 | spinPulse?: boolean
29 | spinReverse?: boolean
30 | pulse?: boolean
31 | beat?: boolean
32 | fade?: boolean
33 | beatFade?: boolean
34 | bounce?: boolean
35 | shake?: boolean
36 | border?: boolean
37 | fixedWidth?: boolean
38 | inverse?: boolean
39 | listItem?: boolean
40 | flip?: FlipProp
41 | size?: SizeProp
42 | pull?: PullProp
43 | rotation?: RotateProp
44 | transform?: string | Transform
45 | symbol?: FaSymbol
46 | style?: CSS.PropertiesHyphen | string
47 | tabIndex?: number;
48 | title?: string;
49 | titleId?: string;
50 | swapOpacity?: boolean;
51 | }
52 |
--------------------------------------------------------------------------------
/src/utils/get-class-list-from-props.js:
--------------------------------------------------------------------------------
1 | // Get CSS class list from a props object
2 | export default function classList(props) {
3 | const {
4 | beat,
5 | fade,
6 | beatFade,
7 | bounce,
8 | shake,
9 | flash,
10 | spin,
11 | spinPulse,
12 | spinReverse,
13 | pulse,
14 | fixedWidth,
15 | inverse,
16 | border,
17 | listItem,
18 | flip,
19 | size,
20 | rotation,
21 | pull
22 | } = props
23 |
24 | // map of CSS class names to properties
25 | const classes = {
26 | 'fa-beat': beat,
27 | 'fa-fade': fade,
28 | 'fa-beat-fade': beatFade,
29 | 'fa-bounce': bounce,
30 | 'fa-shake': shake,
31 | 'fa-flash': flash,
32 | 'fa-spin': spin,
33 | 'fa-spin-reverse': spinReverse,
34 | 'fa-spin-pulse': spinPulse,
35 | 'fa-pulse': pulse,
36 | 'fa-fw': fixedWidth,
37 | 'fa-inverse': inverse,
38 | 'fa-border': border,
39 | 'fa-li': listItem,
40 | 'fa-flip': flip === true,
41 | 'fa-flip-horizontal': flip === 'horizontal' || flip === 'both',
42 | 'fa-flip-vertical': flip === 'vertical' || flip === 'both',
43 | [`fa-${size}`]: typeof size !== 'undefined' && size !== null,
44 | [`fa-rotate-${rotation}`]:
45 | typeof rotation !== 'undefined' && rotation !== null && rotation !== 0,
46 | [`fa-pull-${pull}`]: typeof pull !== 'undefined' && pull !== null,
47 | 'fa-swap-opacity': props.swapOpacity
48 | }
49 |
50 | // map over all the keys in the classes object
51 | // return an array of the keys where the value for the key is not null
52 | return Object.keys(classes)
53 | .map(key => (classes[key] ? key : null))
54 | .filter(key => key)
55 | }
56 |
--------------------------------------------------------------------------------
/DEVELOPMENT.md:
--------------------------------------------------------------------------------
1 | # Developing Svelte Fontawesome
2 |
3 | ## Tasks
4 |
5 | The following commands are available through `npm run`
6 |
7 | | Command | Purpose |
8 | | ------- | ------------------------------------- |
9 | | build | Build this project |
10 | | dist | Build this project in production mode |
11 | | lint | Check linting using ESLint |
12 | | test | Run tests |
13 |
14 | ## Releasing a new version
15 |
16 |
17 |
18 | 1. Edit `package.json` and update the version number
19 | 1. Add new contributors to the `contributors` section
20 | 1. Update the `CHANGELOG.md`
21 | 1. Update the `README.md` contributors section
22 | 1. `npm run build`
23 | 1. `npm publish --tag latest`
24 | 1. `npm publish --tag latest --registry https://npm.fontawesome.com` (publish to Pro registry)
25 | 1. `git add . && git commit -m 'Release VERSION'`
26 | 1. `git push`
27 | 1. Create a [new release](https://github.com/FortAwesome/svelte-fontawesome/releases/new) with `CHANGELOG` details
28 |
29 | ## Authenticating with the npm.fontawesome.com registry
30 |
31 | Contributors with authorization to publish to npm.fontawesome.com will receive an invite
32 | from a Font Awesome project owner.
33 |
34 | 1. Respond to the invite in your email
35 | 1. Let the owner know when you've setup your account
36 | 1. Owner will add you to the team
37 |
38 | You can then run:
39 |
40 | ```
41 | npm login --registry https://npm.fontawesome.com
42 | ```
43 |
44 | - The username is the "slug" for your Cloudsmith account. For example mine is "rob-madole".
45 | - Enter the password that you setup just a few minutes ago.
46 | - It says the your email is PUBLIC. Pretty sure that's false since the auth is through Cloudsmith.
47 | - This doesn't overwrite your standard login, just adds to your `~/.npmrc`
48 |
--------------------------------------------------------------------------------
/src/converter.js:
--------------------------------------------------------------------------------
1 | import camelize from './utils/camelize'
2 |
3 | function capitalize(val) {
4 | return val.charAt(0).toUpperCase() + val.slice(1)
5 | }
6 |
7 | export function styleToObject(style) {
8 | return style
9 | ? style
10 | .split(';')
11 | .map((s) => s.trim())
12 | .filter((s) => s)
13 | .reduce((acc, pair) => {
14 | const i = pair.indexOf(':')
15 | const prop = camelize(pair.slice(0, i))
16 | const value = pair.slice(i + 1).trim()
17 |
18 | prop.startsWith('webkit')
19 | ? (acc[capitalize(prop)] = value)
20 | : (acc[prop] = value)
21 |
22 | return acc
23 | }, {})
24 | : null
25 | }
26 |
27 | export function styleToString(style) {
28 | if (typeof style === 'string') {
29 | return style
30 | }
31 |
32 | return Object.keys(style).reduce((acc, key) => (
33 | acc + key.split(/(?=[A-Z])/).join('-').toLowerCase() + ':' + style[key] + ';'
34 | ), '')
35 | }
36 |
37 | function convert(createElement, element, extraProps = {}) {
38 | if (typeof element === 'string') {
39 | return element
40 | }
41 |
42 | const children = (element.children || []).map((child) => {
43 | return convert(createElement, child)
44 | })
45 |
46 | /* eslint-disable dot-notation */
47 | const mixins = Object.keys(element.attributes || {}).reduce(
48 | (acc, key) => {
49 | const val = element.attributes[key]
50 |
51 | if (key === 'style') {
52 | acc.attrs['style'] = styleToString(val)
53 | } else {
54 | if (key.indexOf('aria-') === 0 || key.indexOf('data-') === 0) {
55 | acc.attrs[key.toLowerCase()] = val
56 | } else {
57 | acc.attrs[camelize(key)] = val
58 | }
59 | }
60 |
61 | return acc
62 | },
63 | { attrs: {} }
64 | )
65 |
66 | /* eslint-enable */
67 |
68 | return createElement(element.tag, { ...mixins.attrs }, children)
69 | }
70 |
71 | export default convert
72 |
--------------------------------------------------------------------------------
/examples/svelte-app/src/App.svelte:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
11 | svelte-fontawesome
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
28 |
29 |
30 |
36 |
37 |
38 |
43 |
44 |
45 |
50 |
51 |
52 |
57 |
58 |
59 |
64 |
65 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | This is the repository for the _official_ Font Awesome Svelte component, _initialized_ by the team behind Font Awesome,
2 | but intended to evolve over time with _community_ contributions.
3 |
4 | # Ways to Contribute
5 |
6 | ## Ask a Question
7 |
8 | Trying to figure out how to make it work? Or how to use it in your scenario?
9 |
10 | 1. Review the [README](README.md)
11 | 1. Get familiar with the documentation for the [SVG with JavaScript](https://fontawesome.com/how-to-use/svg-with-js) implementation,
12 | the framework upon which this component is built. Sometimes the answers you need may be there.
13 | 1. Post any remaining questions on [StackOverflow](https://stackoverflow.com/questions/tagged/svelte-fontawesome) with the tag `svelte-fontawesome`.
14 |
15 | ## Report a Bug
16 |
17 | 1. Create a test case that reproduces the unexpected behavior
18 | 1. [Open a new issue with this template](https://github.com/FortAwesome/svelte-fontawesome/issues/new?template=bug-report.md),
19 | and be sure to include a link to the reproduction you made with StackBlitz.
20 |
21 | ## Submit a Pull Request
22 |
23 | Add tests if you add code.
24 |
25 | ## Everything Else
26 |
27 | - [Request a feature](https://github.com/FortAwesome/svelte-fontawesome/issues/new??title=Feature%20request:feature-name&template=feature-request.md)
28 | - [Request a new icon](https://github.com/FortAwesome/Font-Awesome/issues/new?title=Icon%20request:%20icon-name&template=icon-request.md)
29 |
30 | # Project Goals
31 |
32 | 1. Achieve and maintain feature parity with Font Awesome's [SVG with JavaScript](https://fontawesome.com/how-to-use/svg-with-js) method.
33 |
34 | 1. Keep with best practices in the Svelte development community.
35 |
36 | 1. Stay current with major developments in Svelte and SvelteKit
37 |
38 | 1. Maintain a reasonable level of consistency between this component and the other Font Awesome official JavaScript
39 | framework components.
40 |
41 | # Code of Conduct
42 |
43 | We'll contribute according to the [Code of Conduct](CODE_OF_CONDUCT.md).
44 |
45 | # Wanted: Core Contributors
46 |
47 | We're seeking core contributors to help drive this project. Core contributors:
48 |
49 | 1. Share these goals
50 | 1. Demonstrate competence through contributions
51 | 1. Contribute with conduct fitting with our code of conduct
52 | 1. Want to make this project awesome
53 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | # svelte-fontawesome
6 |
7 | [](https://www.npmjs.com/package/@fortawesome/svelte-fontawesome)
8 |
9 | > Font Awesome Svelte component using SVG with JS
10 |
11 |
12 |
13 | - [Documentation](#documentation)
14 | - [How to Help](#how-to-help)
15 | - [Contributors](#contributors)
16 | - [Releasing this project (only project owners can do this)](#releasing-this-project-only-project-owners-can-do-this)
17 |
18 |
19 |
20 |
21 |
22 | ## Compatibility
23 | | Svelte version | svelte-fontawesome version |
24 | | - | - |
25 | | >= 3.x | 0.2.x |
26 |
27 | _Documentation is not currently available. Check out the `examples` directory to get started._
28 |
29 | _We'll be working on documentation (either in this repo or on fontawesome.com) when time allows._
30 |
31 | ## How to Help
32 |
33 | Review the following docs before diving in:
34 |
35 | - [CONTRIBUTING.md](CONTRIBUTING.md)
36 | - [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md)
37 |
38 | And then:
39 |
40 | 1. Check the existing issue and see if you can help!
41 |
42 | ## Contributors
43 |
44 | The following contributors have either helped to start this project, have contributed
45 | code, are actively maintaining it (including documentation), or in other ways
46 | being awesome contributors to this project. **We'd like to take a moment to recognize them.**
47 |
48 | | Name | GitHub |
49 | | ----------------- | ---------------------------------------------------------- |
50 | | Sean Timm | [@seantimm](https://github.com/seantimm) |
51 | | Akiomi Kamakura | [@akiomik](https://github.com/akiomik) |
52 | | Daniel Senff | [@Dahie](https://github.com/Dahie) |
53 | | Konnng Digital | [@konnng-dev](https://github.com/konnng-dev) |
54 | | Martin Blasko | [@MartinBspheroid](https://github.com/MartinBspheroid) |
55 | | Font Awesome Team | [@FortAwesome](https://github.com/orgs/FortAwesome/people) |
56 |
57 | If we've missed someone (which is quite likely) submit a Pull Request to us and we'll get it resolved.
58 |
59 | ## Releasing this project (only project owners can do this)
60 |
61 | See [DEVELOPMENT.md](DEVELOPMENT.md#release)
62 |
--------------------------------------------------------------------------------
/examples/svelte-app-typescript/src/App.svelte:
--------------------------------------------------------------------------------
1 |
24 |
25 |
26 |
27 |
28 |
29 | svelte-fontawesome (TypeScript edition)
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
46 |
47 |
48 |
54 |
55 |
56 |
61 |
62 |
63 |
68 |
69 |
70 |
75 |
76 |
77 |
82 |
83 |
84 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/examples/svelte-app/README.md:
--------------------------------------------------------------------------------
1 | # Svelte + Vite
2 |
3 | This template should help get you started developing with Svelte in Vite.
4 |
5 | ## Recommended IDE Setup
6 |
7 | [VS Code](https://code.visualstudio.com/) + [Svelte](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode).
8 |
9 | ## Need an official Svelte framework?
10 |
11 | Check out [SvelteKit](https://github.com/sveltejs/kit#readme), which is also powered by Vite. Deploy anywhere with its serverless-first approach and adapt to various platforms, with out of the box support for TypeScript, SCSS, and Less, and easily-added support for mdsvex, GraphQL, PostCSS, Tailwind CSS, and more.
12 |
13 | ## Technical considerations
14 |
15 | **Why use this over SvelteKit?**
16 |
17 | - It brings its own routing solution which might not be preferable for some users.
18 | - It is first and foremost a framework that just happens to use Vite under the hood, not a Vite app.
19 | `vite dev` and `vite build` wouldn't work in a SvelteKit environment, for example.
20 |
21 | This template contains as little as possible to get started with Vite + Svelte, while taking into account the developer experience with regards to HMR and intellisense. It demonstrates capabilities on par with the other `create-vite` templates and is a good starting point for beginners dipping their toes into a Vite + Svelte project.
22 |
23 | Should you later need the extended capabilities and extensibility provided by SvelteKit, the template has been structured similarly to SvelteKit so that it is easy to migrate.
24 |
25 | **Why `global.d.ts` instead of `compilerOptions.types` inside `jsconfig.json` or `tsconfig.json`?**
26 |
27 | Setting `compilerOptions.types` shuts out all other types not explicitly listed in the configuration. Using triple-slash references keeps the default TypeScript setting of accepting type information from the entire workspace, while also adding `svelte` and `vite/client` type information.
28 |
29 | **Why include `.vscode/extensions.json`?**
30 |
31 | Other templates indirectly recommend extensions via the README, but this file allows VS Code to prompt the user to install the recommended extension upon opening the project.
32 |
33 | **Why enable `checkJs` in the JS template?**
34 |
35 | It is likely that most cases of changing variable types in runtime are likely to be accidental, rather than deliberate. This provides advanced typechecking out of the box. Should you like to take advantage of the dynamically-typed nature of JavaScript, it is trivial to change the configuration.
36 |
37 | **Why is HMR not preserving my local component state?**
38 |
39 | HMR state preservation comes with a number of gotchas! It has been disabled by default in both `svelte-hmr` and `@sveltejs/vite-plugin-svelte` due to its often surprising behavior. You can read the details [here](https://github.com/rixo/svelte-hmr#svelte-hmr).
40 |
41 | If you have state that's important to retain within a component, consider creating an external store which would not be replaced by HMR.
42 |
43 | ```js
44 | // store.js
45 | // An extremely simple external store
46 | import { writable } from 'svelte/store'
47 | export default writable(0)
48 | ```
49 |
--------------------------------------------------------------------------------
/src/components/__fixtures__/helpers.js:
--------------------------------------------------------------------------------
1 | import FontAwesomeIcon from '../FontAwesomeIcon.svelte'
2 | import { styleToObject, styleToString } from '../../converter'
3 | import { cleanup, render, screen } from '@testing-library/svelte'
4 | import { parse } from '@fortawesome/fontawesome-svg-core'
5 | import semver from 'semver'
6 |
7 | import svgCorePackageJson from '@fortawesome/fontawesome-svg-core/package.json' with { type: 'json' }
8 | import svgIconsPackageJson from '@fortawesome/free-solid-svg-icons/package.json' with { type: 'json' }
9 |
10 | const SVG_CORE_VERSION = semver.parse(svgCorePackageJson.version)
11 | const SVG_ICONS_VERSION = semver.parse(svgIconsPackageJson.version)
12 |
13 | export const REFERENCE_ICON_BY_STYLE = 0x00
14 | export const ICON_ALIASES = 0x01
15 | export const REFERENCE_ICON_USING_STRING = 0x02
16 | export const USES_A11Y_TITLE = 0x03
17 |
18 | export function coreHasFeature(feature) {
19 | if (feature === ICON_ALIASES) {
20 | // Aliases were not introduced until version 6 so we need to check the
21 | // installed free-solid-svg-icons package as well.
22 | return parse.icon && SVG_ICONS_VERSION.major >= 6
23 | }
24 |
25 | if (feature === USES_A11Y_TITLE) {
26 | // Accessibility changed in version 7 and the title attribute is no longer used
27 | return SVG_CORE_VERSION.major < 7
28 | }
29 |
30 | if (
31 | feature === REFERENCE_ICON_BY_STYLE ||
32 | feature === REFERENCE_ICON_USING_STRING
33 | ) {
34 | return parse.icon
35 | }
36 | }
37 |
38 | function convertToTestResult(component, props) {
39 | const attributes = component.getAttributeNames().reduce((acc, name) => {
40 | return {
41 | ...acc,
42 | [name]: component.getAttribute(name)
43 | }
44 | }, {})
45 |
46 | attributes.style = styleToObject(attributes.style)
47 |
48 | let nodeName = component.nodeName.toLowerCase()
49 | if (component.nodeName === 'svelte:element') {
50 | // temp extreme silliness due to svelte-testing-library issue w/ svelte:options resulting
51 | // in svelte:element instead of proper nodeName - grossly inaccurate but works for now
52 | if (props?.symbol) {
53 | nodeName = 'symbol'
54 | } else if (props?.title) {
55 | nodeName = 'title'
56 | } else {
57 | nodeName = 'svg'
58 | }
59 | }
60 |
61 | return {
62 | id: component.id,
63 | type: nodeName,
64 | props: attributes,
65 | children: component.children.length
66 | ? Array.from(component.children).map((child) =>
67 | convertToTestResult(child, props)
68 | )
69 | : [component.innerHTML]
70 | }
71 | }
72 |
73 | export function mount(props = {}, { createNodeMock } = {}) {
74 | let result = null
75 |
76 | // Conversion for test values to make it easy to copy over new tests from react-fontawesome
77 | if (props.style) {
78 | props.style = styleToString(props.style)
79 | }
80 |
81 | props.class = props.class || props.className
82 |
83 | render(FontAwesomeIcon, { props })
84 | const domComponent = screen.queryByRole('img', { hidden: true })
85 | if (domComponent) {
86 | result = convertToTestResult(domComponent, props)
87 | }
88 |
89 | cleanup()
90 |
91 | return result
92 | }
93 |
--------------------------------------------------------------------------------
/examples/svelte-app-typescript/README.md:
--------------------------------------------------------------------------------
1 | # Svelte + TS + Vite
2 |
3 | This template should help get you started developing with Svelte and TypeScript in Vite.
4 |
5 | ## Recommended IDE Setup
6 |
7 | [VS Code](https://code.visualstudio.com/) + [Svelte](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode).
8 |
9 | ## Need an official Svelte framework?
10 |
11 | Check out [SvelteKit](https://github.com/sveltejs/kit#readme), which is also powered by Vite. Deploy anywhere with its serverless-first approach and adapt to various platforms, with out of the box support for TypeScript, SCSS, and Less, and easily-added support for mdsvex, GraphQL, PostCSS, Tailwind CSS, and more.
12 |
13 | ## Technical considerations
14 |
15 | **Why use this over SvelteKit?**
16 |
17 | - It brings its own routing solution which might not be preferable for some users.
18 | - It is first and foremost a framework that just happens to use Vite under the hood, not a Vite app.
19 | `vite dev` and `vite build` wouldn't work in a SvelteKit environment, for example.
20 |
21 | This template contains as little as possible to get started with Vite + TypeScript + Svelte, while taking into account the developer experience with regards to HMR and intellisense. It demonstrates capabilities on par with the other `create-vite` templates and is a good starting point for beginners dipping their toes into a Vite + Svelte project.
22 |
23 | Should you later need the extended capabilities and extensibility provided by SvelteKit, the template has been structured similarly to SvelteKit so that it is easy to migrate.
24 |
25 | **Why `global.d.ts` instead of `compilerOptions.types` inside `jsconfig.json` or `tsconfig.json`?**
26 |
27 | Setting `compilerOptions.types` shuts out all other types not explicitly listed in the configuration. Using triple-slash references keeps the default TypeScript setting of accepting type information from the entire workspace, while also adding `svelte` and `vite/client` type information.
28 |
29 | **Why include `.vscode/extensions.json`?**
30 |
31 | Other templates indirectly recommend extensions via the README, but this file allows VS Code to prompt the user to install the recommended extension upon opening the project.
32 |
33 | **Why enable `allowJs` in the TS template?**
34 |
35 | While `allowJs: false` would indeed prevent the use of `.js` files in the project, it does not prevent the use of JavaScript syntax in `.svelte` files. In addition, it would force `checkJs: false`, bringing the worst of both worlds: not being able to guarantee the entire codebase is TypeScript, and also having worse typechecking for the existing JavaScript. In addition, there are valid use cases in which a mixed codebase may be relevant.
36 |
37 | **Why is HMR not preserving my local component state?**
38 |
39 | HMR state preservation comes with a number of gotchas! It has been disabled by default in both `svelte-hmr` and `@sveltejs/vite-plugin-svelte` due to its often surprising behavior. You can read the details [here](https://github.com/rixo/svelte-hmr#svelte-hmr).
40 |
41 | If you have state that's important to retain within a component, consider creating an external store which would not be replaced by HMR.
42 |
43 | ```ts
44 | // store.ts
45 | // An extremely simple external store
46 | import { writable } from 'svelte/store'
47 | export default writable(0)
48 | ```
49 |
--------------------------------------------------------------------------------
/src/components/FontAwesomeIcon.svelte:
--------------------------------------------------------------------------------
1 |
100 |
101 | {#if result}
102 |
103 | {/if}
104 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as
6 | contributors and maintainers pledge to making participation in our project and
7 | our community a harassment-free experience for everyone, regardless of age, body
8 | size, disability, ethnicity, gender identity and expression, level of experience,
9 | nationality, personal appearance, race, religion, or sexual identity and
10 | orientation.
11 |
12 | ## Our Standards
13 |
14 | Examples of behavior that contributes to creating a positive environment
15 | include:
16 |
17 | * Using welcoming and inclusive language
18 | * Being respectful of differing viewpoints and experiences
19 | * Gracefully accepting constructive criticism
20 | * Focusing on what is best for the community
21 | * Showing empathy towards other community members
22 |
23 | Examples of unacceptable behavior by participants include:
24 |
25 | * The use of sexualized language or imagery and unwelcome sexual attention or
26 | advances
27 | * Trolling, insulting/derogatory comments, and personal or political attacks
28 | * Public or private harassment
29 | * Publishing others' private information, such as a physical or electronic
30 | address, without explicit permission
31 | * Other conduct which could reasonably be considered inappropriate in a
32 | professional setting
33 |
34 | ## Our Responsibilities
35 |
36 | Project maintainers are responsible for clarifying the standards of acceptable
37 | behavior and are expected to take appropriate and fair corrective action in
38 | response to any instances of unacceptable behavior.
39 |
40 | Project maintainers have the right and responsibility to remove, edit, or
41 | reject comments, commits, code, wiki edits, issues, and other contributions
42 | that are not aligned to this Code of Conduct, or to ban temporarily or
43 | permanently any contributor for other behaviors that they deem inappropriate,
44 | threatening, offensive, or harmful.
45 |
46 | ## Scope
47 |
48 | This Code of Conduct applies both within project spaces and in public spaces
49 | when an individual is representing the project or its community. Examples of
50 | representing a project or community include using an official project e-mail
51 | address, posting via an official social media account, or acting as an appointed
52 | representative at an online or offline event. Representation of a project may be
53 | further defined and clarified by project maintainers.
54 |
55 | ## Enforcement
56 |
57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
58 | reported by contacting the project team at . All
59 | complaints will be reviewed and investigated and will result in a response that
60 | is deemed necessary and appropriate to the circumstances. The project team is
61 | obligated to maintain confidentiality with regard to the reporter of an incident.
62 | Further details of specific enforcement policies may be posted separately.
63 |
64 | Project maintainers who do not follow or enforce the Code of Conduct in good
65 | faith may face temporary or permanent repercussions as determined by other
66 | members of the project's leadership.
67 |
68 | ## Attribution
69 |
70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71 | available at [https://contributor-covenant.org/version/1/4][version]
72 |
73 | [homepage]: https://contributor-covenant.org
74 | [version]: https://contributor-covenant.org/version/1/4/
75 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@fortawesome/svelte-fontawesome",
3 | "description": "Svelte component for Font Awesome",
4 | "version": "0.2.4",
5 | "type": "module",
6 | "svelte": "src/index.js",
7 | "exports": {
8 | ".": {
9 | "types": "./index.d.ts",
10 | "svelte": "./src/index.js"
11 | }
12 | },
13 | "main": "index.js",
14 | "module": "index.es.js",
15 | "jsnext:main": "index.es.js",
16 | "types": "index.d.ts",
17 | "homepage": "https://github.com/FortAwesome/svelte-fontawesome",
18 | "repository": {
19 | "type": "git",
20 | "url": "https://github.com/FortAwesome/svelte-fontawesome.git"
21 | },
22 | "contributors": [
23 | "Font Awesome Team ",
24 | "Sean Timm ",
25 | "Akiomi Kamakura ",
26 | "Daniel Senff ",
27 | "Konnng Digital ",
28 | "Martin Blasko "
29 | ],
30 | "license": "MIT",
31 | "scripts": {
32 | "build": "rollup -c rollup.config.js",
33 | "dist": "cross-env NODE_ENV=production npm run build",
34 | "lint": "eslint src",
35 | "prettier": "pretty-quick --pattern src/** --staged",
36 | "prepack": "npm run dist",
37 | "test": "vitest run",
38 | "test:watch": "vitest",
39 | "test:ui": "vitest --ui",
40 | "install.5": "npm --no-save install @fortawesome/fontawesome-svg-core@1.2.x @fortawesome/free-solid-svg-icons@5.x",
41 | "install.6": "npm --no-save install @fortawesome/fontawesome-svg-core@6.x @fortawesome/free-solid-svg-icons@6.x",
42 | "clean": "rm -f index.js && rm -f index.es.js"
43 | },
44 | "lint-staged": {
45 | "README.md": [
46 | "markdown-toc -i",
47 | "git add README.md"
48 | ]
49 | },
50 | "peerDependencies": {
51 | "@fortawesome/fontawesome-svg-core": "~1 || ~6 || ~7",
52 | "svelte": "~3 || ~4 || ~5"
53 | },
54 | "devDependencies": {
55 | "@babel/core": "^7.18.6",
56 | "@babel/eslint-parser": "^7.18.2",
57 | "@babel/plugin-external-helpers": "^7.18.6",
58 | "@babel/preset-env": "^7.18.6",
59 | "@babel/preset-stage-3": "^7.8.3",
60 | "@fortawesome/fontawesome-svg-core": "^7",
61 | "@fortawesome/free-solid-svg-icons": "^7",
62 | "@pyoner/svelte-types": "^3.4.4-2",
63 | "@rollup/plugin-babel": "^5.3.1",
64 | "@rollup/plugin-commonjs": "^22.0.1",
65 | "@rollup/plugin-node-resolve": "^13.3.0",
66 | "@sveltejs/vite-plugin-svelte": "^2.5.3",
67 | "@testing-library/jest-dom": "^5.17.0",
68 | "@testing-library/svelte": "^5.2.8",
69 | "@vitest/ui": "^3.2.4",
70 | "browserslist": "^4.21.2",
71 | "caniuse-lite": "^1.0.30001299",
72 | "cross-env": "^7.0.3",
73 | "eslint": "^8.16.0",
74 | "eslint-config-standard": "^17.0.0",
75 | "eslint-plugin-compat": "^4.0.2",
76 | "eslint-plugin-import": "^2.26.0",
77 | "eslint-plugin-n": "^15.2.4",
78 | "eslint-plugin-promise": "^6.0.0",
79 | "eslint-plugin-svelte3": "^4.0.0",
80 | "husky": "^7.0.4",
81 | "jsdom": "^26.1.0",
82 | "lint-staged": "^12.1.7",
83 | "markdown-toc": "^1.2.0",
84 | "prettier": "^2.7.1",
85 | "pretty-quick": "^3.1.3",
86 | "rollup": "^2.76.0",
87 | "rollup-plugin-svelte": "^7.1.0",
88 | "semver": "^7.3.7",
89 | "svelte": ">=3.x",
90 | "vitest": "^3.2.4"
91 | },
92 | "files": [
93 | "index.js",
94 | "index.es.js",
95 | "index.d.ts",
96 | "src"
97 | ],
98 | "browserslist": [
99 | "> 1%",
100 | "last 2 versions",
101 | "ie > 10"
102 | ],
103 | "husky": {
104 | "hooks": {
105 | "pre-commit": "npm run lint && npm run prettier && lint-staged"
106 | }
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/src/utils/__tests__/get-class-list-from-props.test.js:
--------------------------------------------------------------------------------
1 | import getClassList from '../get-class-list-from-props'
2 |
3 | describe('get class list', () => {
4 | test('test the booleans', () => {
5 | const props = {
6 | border: true,
7 | fixedWidth: true,
8 | inverse: true,
9 | listItem: true,
10 | pulse: true,
11 | spin: true,
12 | spinPulse: true,
13 | spinReverse: true,
14 | beat: true,
15 | fade: true,
16 | beatFade: true,
17 | bounce: true,
18 | shake: true,
19 | swapOpacity: true,
20 | flip: true
21 | }
22 |
23 | const classList = getClassList(props)
24 |
25 | expect(classList).toStrictEqual([
26 | 'fa-beat',
27 | 'fa-fade',
28 | 'fa-beat-fade',
29 | 'fa-bounce',
30 | 'fa-shake',
31 | 'fa-spin',
32 | 'fa-spin-reverse',
33 | 'fa-spin-pulse',
34 | 'fa-pulse',
35 | 'fa-fw',
36 | 'fa-inverse',
37 | 'fa-border',
38 | 'fa-li',
39 | 'fa-flip',
40 | 'fa-swap-opacity'
41 | ])
42 | })
43 |
44 | test('size', () => {
45 | function testSize(size) {
46 | expect(getClassList({ size })).toStrictEqual([`fa-${size}`])
47 | }
48 |
49 | testSize('xs')
50 | })
51 |
52 | test('flip', () => {
53 | const HORIZONTAL = 'fa-flip-horizontal'
54 | const VERTICAL = 'fa-flip-vertical'
55 | const FLIP_ANIMATION = 'fa-flip'
56 |
57 | const horizontalList = getClassList({
58 | flip: 'horizontal'
59 | })
60 |
61 | const verticalList = getClassList({
62 | flip: 'vertical'
63 | })
64 |
65 | const bothList = getClassList({
66 | flip: 'both'
67 | })
68 |
69 | const flipAnimationOnly = getClassList({
70 | flip: true
71 | })
72 |
73 | expect(horizontalList).toContain(HORIZONTAL)
74 | expect(verticalList).toContain(VERTICAL)
75 |
76 | expect(bothList.length).toBe(2)
77 | expect(bothList).toContain(HORIZONTAL)
78 | expect(bothList).toContain(VERTICAL)
79 |
80 | expect(flipAnimationOnly).toContain(FLIP_ANIMATION)
81 | })
82 |
83 | test('size', () => {
84 | function testSize(size) {
85 | expect(getClassList({ size })).toStrictEqual([`fa-${size}`])
86 | }
87 |
88 | testSize('xs')
89 | })
90 |
91 | test('rotation', () => {
92 | function testRotation(rotation) {
93 | expect(getClassList({ rotation })).toStrictEqual([
94 | `fa-rotate-${rotation}`
95 | ])
96 | }
97 |
98 | testRotation(90)
99 | testRotation(180)
100 | testRotation(270)
101 | })
102 |
103 | test('pull', () => {
104 | function testPull(pull) {
105 | expect(getClassList({ pull })).toStrictEqual([`fa-pull-${pull}`])
106 | }
107 |
108 | testPull('left')
109 | testPull('right')
110 | })
111 |
112 | describe('when some props are null', () => {
113 | function testNulls(prop) {
114 | const NUM_CLASSES = 6
115 |
116 | const props = {
117 | spin: true,
118 | pulse: true,
119 | fixedWidth: true,
120 | inverse: true,
121 | border: true,
122 | listItem: true,
123 | [prop]: null
124 | }
125 |
126 | const classList = getClassList(props)
127 | expect(classList.length).toBe(NUM_CLASSES)
128 | expect(classList).toStrictEqual([
129 | 'fa-spin',
130 | 'fa-pulse',
131 | 'fa-fw',
132 | 'fa-inverse',
133 | 'fa-border',
134 | 'fa-li'
135 | ])
136 | }
137 |
138 | test('pull', () => {
139 | testNulls('pull')
140 | })
141 |
142 | test('rotation', () => {
143 | testNulls('rotation')
144 | })
145 |
146 | test('size', () => {
147 | testNulls('size')
148 | })
149 | })
150 | })
151 |
--------------------------------------------------------------------------------
/src/components/__tests__/FontAwesomeIcon.test.js:
--------------------------------------------------------------------------------
1 | import { vi } from 'vitest'
2 | import * as fontawesome from '@fortawesome/fontawesome-svg-core'
3 | import log from '../../logger'
4 | import { faTimes } from '@fortawesome/free-solid-svg-icons'
5 | import { faCoffee, faCircle, faSpartan } from '../__fixtures__/icons'
6 | import {
7 | coreHasFeature,
8 | REFERENCE_ICON_USING_STRING,
9 | REFERENCE_ICON_BY_STYLE,
10 | ICON_ALIASES,
11 | USES_A11Y_TITLE,
12 | mount
13 | } from '../__fixtures__/helpers'
14 |
15 | vi.mock('../../logger')
16 |
17 | beforeEach(() => {
18 | fontawesome.library.add(faCoffee, faCircle, faSpartan)
19 | })
20 |
21 | afterEach(() => {
22 | fontawesome.library.reset()
23 | })
24 |
25 | test('using a FAT icon using array format', () => {
26 | const vm = mount({
27 | icon: ['fat', 'spartan']
28 | })
29 |
30 | expect(vm.type).toBe('svg')
31 | expect(vm.props.class.includes('fa-spartan')).toBeTruthy()
32 | })
33 |
34 | if (coreHasFeature(ICON_ALIASES)) {
35 | test('find a free-solid-svg-icon with array format', () => {
36 | fontawesome.library.add(faTimes)
37 | const vm = mount({ icon: ['fas', 'xmark'] })
38 |
39 | expect(vm.type).toBe('svg')
40 | expect(vm.props.class.includes('fa-xmark')).toBeTruthy()
41 | })
42 |
43 | test('find a free-solid-svg-icon that is an alias ', () => {
44 | fontawesome.library.add(faTimes)
45 | const vm = mount({ icon: ['fas', 'close'] })
46 |
47 | expect(vm.type).toBe('svg')
48 | expect(vm.props.class.includes('fa-xmark')).toBeTruthy()
49 | })
50 | }
51 |
52 | if (coreHasFeature(REFERENCE_ICON_USING_STRING)) {
53 | test('find an icon using string format', () => {
54 | const vm = mount({ icon: 'fa-coffee' })
55 |
56 | expect(vm.type).toBe('svg')
57 | expect(vm.props.class.includes('fa-coffee')).toBeTruthy()
58 | })
59 |
60 | test('find an icon using string format with style', () => {
61 | const vm = mount({ icon: 'fa-solid fa-coffee' })
62 |
63 | expect(vm.type).toBe('svg')
64 | expect(vm.props.class.includes('fa-coffee')).toBeTruthy()
65 | })
66 | }
67 |
68 | if (coreHasFeature(REFERENCE_ICON_BY_STYLE)) {
69 | test('find a THIN icon with array format', () => {
70 | const vm = mount({ icon: ['thin', 'spartan'] })
71 |
72 | expect(vm.type).toBe('svg')
73 | expect(vm.props.class.includes('fa-spartan')).toBeTruthy()
74 | })
75 |
76 | test('find a FA-THIN icon with array format', () => {
77 | const vm = mount({ icon: ['fa-thin', 'spartan'] })
78 |
79 | expect(vm.type).toBe('svg')
80 | expect(vm.props.class.includes('fa-spartan')).toBeTruthy()
81 | })
82 | }
83 |
84 | test('using imported object from svg icons package', () => {
85 | const vm = mount({
86 | icon: faTimes
87 | })
88 |
89 | expect(vm.type).toBe('svg')
90 | })
91 |
92 | test('using pack and name', () => {
93 | const vm = mount({
94 | icon: ['fas', 'coffee'],
95 | style: { backgroundColor: 'white' }
96 | })
97 |
98 | expect(vm.type).toBe('svg')
99 | expect(vm.props.class.includes('fa-coffee')).toBeTruthy()
100 | expect(vm.props['aria-hidden']).toBe('true')
101 | expect(vm.props['data-icon']).toBe('coffee')
102 | expect(vm.props.style).toEqual({ backgroundColor: 'white' })
103 | })
104 |
105 | test('using pack common names', () => {
106 | const vm = mount({ icon: 'coffee' })
107 |
108 | expect(vm.type).toBe('svg')
109 | expect(vm.props.class.includes('fa-coffee')).toBeTruthy()
110 | })
111 |
112 | test('using pack common names not added to library', () => {
113 | const vm = mount({ icon: 'spinner' })
114 | expect(vm).toBeNull()
115 | expect(log.mock.calls.length).toBe(1)
116 | expect(log.mock.calls[0][0]).toEqual(
117 | expect.stringContaining('Could not find icon')
118 | )
119 | })
120 |
121 | test('using icon', () => {
122 | const vm = mount({ icon: faCoffee })
123 |
124 | expect(vm.type).toBe('svg')
125 | expect(vm.props.class.includes('fa-coffee')).toBeTruthy()
126 | })
127 |
128 | test('using border', () => {
129 | const vm = mount({ icon: faCoffee, border: true })
130 |
131 | expect(vm.props.class.includes('fa-border')).toBeTruthy()
132 | })
133 |
134 | test('using fixedWidth', () => {
135 | const vm = mount({ icon: faCoffee, fixedWidth: true })
136 |
137 | expect(vm.props.class.includes('fa-fw')).toBeTruthy()
138 | })
139 |
140 | test('using inverse', () => {
141 | const vm = mount({ icon: faCoffee, inverse: true })
142 |
143 | expect(vm.props.class.includes('fa-inverse')).toBeTruthy()
144 | })
145 |
146 | describe('using flip', () => {
147 | test('horizontal', () => {
148 | const vm = mount({ icon: faCoffee, flip: 'horizontal' })
149 |
150 | expect(vm.props.class.includes('fa-flip-horizontal')).toBeTruthy()
151 | })
152 |
153 | test('vertical', () => {
154 | const vm = mount({ icon: faCoffee, flip: 'vertical' })
155 |
156 | expect(vm.props.class.includes('fa-flip-vertical')).toBeTruthy()
157 | })
158 |
159 | test('both', () => {
160 | const vm = mount({ icon: faCoffee, flip: 'both' })
161 |
162 | expect(vm.props.class.includes('fa-flip-horizontal')).toBeTruthy()
163 | expect(vm.props.class.includes('fa-flip-vertical')).toBeTruthy()
164 | })
165 |
166 | test('animation', () => {
167 | const vm = mount({ icon: faCoffee, flip: true })
168 |
169 | expect(vm.props.class.includes('fa-flip')).toBeTruthy()
170 | })
171 | })
172 |
173 | test('using listItem', () => {
174 | const vm = mount({ icon: faCoffee, listItem: true })
175 |
176 | expect(vm.props.class.includes('fa-li')).toBeTruthy()
177 | })
178 |
179 | describe('using pull', () => {
180 | test('right', () => {
181 | const vm = mount({ icon: faCoffee, pull: 'right' })
182 |
183 | expect(vm.props.class.includes('fa-pull-right')).toBeTruthy()
184 | })
185 |
186 | test('left', () => {
187 | const vm = mount({ icon: faCoffee, pull: 'left' })
188 |
189 | expect(vm.props.class.includes('fa-pull-left')).toBeTruthy()
190 | })
191 | })
192 |
193 | test('using pulse', () => {
194 | const vm = mount({ icon: faCoffee, pulse: true })
195 |
196 | expect(vm.props.class.includes('fa-pulse')).toBeTruthy()
197 | })
198 |
199 | describe('using rotation', () => {
200 | test('0', () => {
201 | const vm = mount({ icon: faCoffee, rotation: 0 })
202 |
203 | expect(vm.props.class.includes('fa-rotate-')).toBeFalsy()
204 | })
205 |
206 | test('90', () => {
207 | const vm = mount({ icon: faCoffee, rotation: 90 })
208 |
209 | expect(vm.props.class.includes('fa-rotate-90')).toBeTruthy()
210 | })
211 |
212 | test('180', () => {
213 | const vm = mount({ icon: faCoffee, rotation: 180 })
214 |
215 | expect(vm.props.class.includes('fa-rotate-180')).toBeTruthy()
216 | })
217 |
218 | test('270', () => {
219 | const vm = mount({ icon: faCoffee, rotation: 270 })
220 |
221 | expect(vm.props.class.includes('fa-rotate-270')).toBeTruthy()
222 | })
223 | })
224 |
225 | test('using size', () => {
226 | ;[
227 | '2xs',
228 | 'xs',
229 | 'sm',
230 | 'lg',
231 | 'xl',
232 | '2xl',
233 | '1x',
234 | '2x',
235 | '3x',
236 | '4x',
237 | '5x',
238 | '6x',
239 | '7x',
240 | '8x',
241 | '9x',
242 | '10x'
243 | ].forEach((size) => {
244 | const vm = mount({ icon: faCoffee, size })
245 |
246 | expect(vm.props.class.includes(`fa-${size}`)).toBeTruthy()
247 | })
248 | })
249 |
250 | describe('using beat', () => {
251 | test('setting beat prop to true adds fa-beat class', () => {
252 | const vm = mount({ icon: faCoffee, beat: true })
253 |
254 | expect(vm.props.class.includes('fa-beat')).toBeTruthy()
255 | })
256 |
257 | test('setting beat prop to false after setting it to true results in no fa-beat class', () => {
258 | let vm = mount({ icon: faCoffee, beat: true })
259 | expect(vm.props.class.includes('fa-beat')).toBeTruthy()
260 | vm = mount({ icon: faCoffee, beat: false })
261 | expect(vm.props.class.includes('fa-beat')).toBeFalsy()
262 | })
263 | })
264 |
265 | describe('using fade', () => {
266 | test('setting fade prop to true adds fa-fade class', () => {
267 | const vm = mount({ icon: faCoffee, fade: true })
268 |
269 | expect(vm.props.class.includes('fa-fade')).toBeTruthy()
270 | })
271 |
272 | test('setting fade prop to false after setting it to true results in no fa-fade class', () => {
273 | let vm = mount({ icon: faCoffee, fade: true })
274 | expect(vm.props.class.includes('fa-fade')).toBeTruthy()
275 | vm = mount({ icon: faCoffee, fade: false })
276 | expect(vm.props.class.includes('fa-fade')).toBeFalsy()
277 | })
278 | })
279 |
280 | describe('using beatFade', () => {
281 | test('setting beatFade prop to true adds fa-beat-fade class', () => {
282 | const vm = mount({ icon: faCoffee, beatFade: true })
283 |
284 | expect(vm.props.class.includes('fa-beat-fade')).toBeTruthy()
285 | })
286 |
287 | test('setting beatFade prop to false after setting it to true results in no fa-beat-fade class', () => {
288 | let vm = mount({ icon: faCoffee, beatFade: true })
289 | expect(vm.props.class.includes('fa-beat-fade')).toBeTruthy()
290 | vm = mount({ icon: faCoffee, beatFade: false })
291 | expect(vm.props.class.includes('fa-beat-fade')).toBeFalsy()
292 | })
293 | })
294 |
295 | describe('using bounce', () => {
296 | test('setting bounce prop to true adds fa-bounce class', () => {
297 | const vm = mount({ icon: faCoffee, bounce: true })
298 |
299 | expect(vm.props.class.includes('fa-bounce')).toBeTruthy()
300 | })
301 |
302 | test('setting bounce prop to false after setting it to true results in no fa-bounce class', () => {
303 | let vm = mount({ icon: faCoffee, bounce: true })
304 | expect(vm.props.class.includes('fa-bounce')).toBeTruthy()
305 | vm = mount({ icon: faCoffee, bounce: false })
306 | expect(vm.props.class.includes('fa-bounce')).toBeFalsy()
307 | })
308 | })
309 |
310 | describe('using shake', () => {
311 | test('setting shake prop to true adds fa-shake class', () => {
312 | const vm = mount({ icon: faCoffee, shake: true })
313 |
314 | expect(vm.props.class.includes('fa-shake')).toBeTruthy()
315 | })
316 |
317 | test('setting shake prop to false after setting it to true results in no fa-shake class', () => {
318 | let vm = mount({ icon: faCoffee, shake: true })
319 | expect(vm.props.class.includes('fa-shake')).toBeTruthy()
320 | vm = mount({ icon: faCoffee, shake: false })
321 | expect(vm.props.class.includes('fa-shake')).toBeFalsy()
322 | })
323 | })
324 |
325 | describe('using spin', () => {
326 | test('setting spin prop to true adds fa-spin class', () => {
327 | const vm = mount({ icon: faCoffee, spin: true })
328 |
329 | expect(vm.props.class.includes('fa-spin')).toBeTruthy()
330 | })
331 |
332 | test('setting spinReverse and spinPulse prop to true adds fa-spin-reverse and fa-spin-pulse class', () => {
333 | const vm = mount({ icon: faCoffee, spinReverse: true, spinPulse: true })
334 |
335 | expect(vm.props.class.includes('fa-spin-reverse')).toBeTruthy()
336 | expect(vm.props.class.includes('fa-spin-pulse')).toBeTruthy()
337 | })
338 |
339 | test('setting spin prop to false after setting it to true results in no fa-spin class', () => {
340 | let vm = mount({ icon: faCoffee, spin: true })
341 | expect(vm.props.class.includes('fa-spin')).toBeTruthy()
342 | vm = mount({ icon: faCoffee, spin: false })
343 | expect(vm.props.class.includes('fa-spin')).toBeFalsy()
344 | })
345 |
346 | test('setting spinPulse prop to false after setting it to true results in no fa-spin-pulse class', () => {
347 | let vm = mount({ icon: faCoffee, spinPulse: true })
348 | expect(vm.props.class.includes('fa-spin-pulse')).toBeTruthy()
349 | vm = mount({ icon: faCoffee, spinPulse: false })
350 | expect(vm.props.class.includes('fa-spin-pulse')).toBeFalsy()
351 | })
352 |
353 | test('setting spinReverse prop to false after setting it to true results in no fa-spin-reverse class', () => {
354 | let vm = mount({ icon: faCoffee, spinReverse: true })
355 | expect(vm.props.class.includes('fa-spin-reverse')).toBeTruthy()
356 | vm = mount({ icon: faCoffee, spinReverse: false })
357 | expect(vm.props.class.includes('fa-spin-reverse')).toBeFalsy()
358 | })
359 | })
360 |
361 | test('using class', () => {
362 | const vm = mount({ icon: faCoffee, class: 'highlight' })
363 |
364 | expect(vm.props.class.includes('highlight')).toBeTruthy()
365 | })
366 |
367 | describe('using transform', () => {
368 | test('string', () => {
369 | const vm = mount({
370 | icon: faCoffee,
371 | transform: 'grow-40 left-4 rotate-15',
372 | style: { backgroundColor: 'white' }
373 | })
374 |
375 | expect(vm.props.style).toEqual({
376 | backgroundColor: 'white',
377 | transformOrigin: '0.375em 0.5em'
378 | })
379 | })
380 |
381 | test('object', () => {
382 | const vm = mount({
383 | icon: faCoffee,
384 | transform: {
385 | flipX: false,
386 | flipY: false,
387 | rotate: 15,
388 | size: 56,
389 | x: -4,
390 | y: 0
391 | }
392 | })
393 |
394 | expect(vm.props.style).toEqual({ transformOrigin: '0.375em 0.5em' })
395 | })
396 | })
397 |
398 | describe('mask', () => {
399 | test('will add icon', () => {
400 | const vm = mount({ icon: faCoffee, mask: faCircle })
401 |
402 | expect(vm.children.length).toBe(2)
403 | expect(vm.children[1].props.hasOwnProperty('clippath')).toBeTruthy() // eslint-disable-line no-prototype-builtins
404 | })
405 |
406 | test('will use maskId', () => {
407 | const vm = mount({ icon: faCoffee, mask: faCircle, maskId: 'circle-mask' })
408 |
409 | expect(vm.children[0].children[0].props.id).toEqual('clip-circle-mask')
410 | expect(vm.children[0].children[1].props.id).toEqual('mask-circle-mask')
411 | expect(vm.children[1].props.mask).toEqual('url(#mask-circle-mask)')
412 | expect(vm.children[1].props.clippath).toEqual('url(#clip-circle-mask)')
413 | })
414 | })
415 |
416 | describe('symbol', () => {
417 | test('will not create a symbol', () => {
418 | const vm = mount({ icon: faCoffee })
419 | expect(vm.type).toBe('svg')
420 | })
421 |
422 | test('will create a symbol', () => {
423 | const vm = mount({ icon: faCoffee, symbol: 'coffee-icon' })
424 |
425 | expect(vm.type).toBe('symbol')
426 | expect(vm.id).toBe('coffee-icon')
427 | })
428 | })
429 |
430 | describe('swap opacity', () => {
431 | test('setting swapOpacity prop to true adds fa-swap-opacity class', () => {
432 | const vm = mount({ icon: faCoffee, swapOpacity: true })
433 |
434 | expect(vm.props.class.includes('fa-swap-opacity')).toBeTruthy()
435 | })
436 |
437 | test('setting swapOpacity prop to false after setting it to true results in no fa-swap-opacity class', () => {
438 | let vm = mount({ icon: faCoffee, swapOpacity: true })
439 | expect(vm.props.class.includes('fa-swap-opacity')).toBeTruthy()
440 | vm = mount({ icon: faCoffee, swapOpacity: false })
441 | expect(vm.props.class.includes('fa-swap-opacity')).toBeFalsy()
442 | })
443 | })
444 |
445 | if (coreHasFeature(USES_A11Y_TITLE)) {
446 | describe('title', () => {
447 | test('will not add a title element', () => {
448 | const vm = mount({ icon: faCoffee })
449 |
450 | expect(vm.children[0].type).not.toBe('title')
451 | })
452 |
453 | test('will add a title element', () => {
454 | const vm = mount({ icon: faCoffee, title: 'Coffee' })
455 |
456 | expect(vm.children[0].type).toBe('title')
457 | expect(vm.children[0].children[0]).toBe('Coffee')
458 | })
459 |
460 | test('will use an explicit titleId', () => {
461 | const vm = mount({
462 | icon: faCoffee,
463 | title: 'Coffee',
464 | titleId: 'coffee-title'
465 | })
466 |
467 | expect(vm.props['aria-labelledby']).toBe(
468 | 'svg-inline--fa-title-coffee-title'
469 | )
470 | expect(vm.children[0].props).toEqual(
471 | expect.objectContaining({ id: 'svg-inline--fa-title-coffee-title' })
472 | )
473 | })
474 | })
475 |
476 | describe('using titleId', () => {
477 | test('setting titleId prop reflects in the aria-labelledby attribute', () => {
478 | const titleId = 'foo'
479 | const vm = mount({ icon: faCoffee, titleId, title: 'Coffee' })
480 | const ariaLabelledby = vm.props['aria-labelledby']
481 | expect(ariaLabelledby.includes(titleId)).toBeTruthy()
482 | })
483 | })
484 | }
485 |
--------------------------------------------------------------------------------
/index.es.js:
--------------------------------------------------------------------------------
1 | import { parse, icon } from '@fortawesome/fontawesome-svg-core';
2 |
3 | function run(fn) {
4 | return fn();
5 | }
6 | function blank_object() {
7 | return Object.create(null);
8 | }
9 | function run_all(fns) {
10 | fns.forEach(run);
11 | }
12 | function compute_rest_props(props, keys) {
13 | const rest = {};
14 | keys = new Set(keys);
15 | for (const k in props)
16 | if (!keys.has(k) && k[0] !== '$')
17 | rest[k] = props[k];
18 | return rest;
19 | }
20 |
21 | let current_component;
22 | function set_current_component(component) {
23 | current_component = component;
24 | }
25 |
26 | const _boolean_attributes = [
27 | 'allowfullscreen',
28 | 'allowpaymentrequest',
29 | 'async',
30 | 'autofocus',
31 | 'autoplay',
32 | 'checked',
33 | 'controls',
34 | 'default',
35 | 'defer',
36 | 'disabled',
37 | 'formnovalidate',
38 | 'hidden',
39 | 'inert',
40 | 'ismap',
41 | 'loop',
42 | 'multiple',
43 | 'muted',
44 | 'nomodule',
45 | 'novalidate',
46 | 'open',
47 | 'playsinline',
48 | 'readonly',
49 | 'required',
50 | 'reversed',
51 | 'selected'
52 | ];
53 | /**
54 | * List of HTML boolean attributes (e.g. ` `).
55 | * Source: https://html.spec.whatwg.org/multipage/indices.html
56 | */
57 | const boolean_attributes = new Set([..._boolean_attributes]);
58 |
59 | const invalid_attribute_name_character = /[\s'">/=\u{FDD0}-\u{FDEF}\u{FFFE}\u{FFFF}\u{1FFFE}\u{1FFFF}\u{2FFFE}\u{2FFFF}\u{3FFFE}\u{3FFFF}\u{4FFFE}\u{4FFFF}\u{5FFFE}\u{5FFFF}\u{6FFFE}\u{6FFFF}\u{7FFFE}\u{7FFFF}\u{8FFFE}\u{8FFFF}\u{9FFFE}\u{9FFFF}\u{AFFFE}\u{AFFFF}\u{BFFFE}\u{BFFFF}\u{CFFFE}\u{CFFFF}\u{DFFFE}\u{DFFFF}\u{EFFFE}\u{EFFFF}\u{FFFFE}\u{FFFFF}\u{10FFFE}\u{10FFFF}]/u;
60 | // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2
61 | // https://infra.spec.whatwg.org/#noncharacter
62 | function spread(args, attrs_to_add) {
63 | const attributes = Object.assign({}, ...args);
64 | if (attrs_to_add) {
65 | const classes_to_add = attrs_to_add.classes;
66 | const styles_to_add = attrs_to_add.styles;
67 | if (classes_to_add) {
68 | if (attributes.class == null) {
69 | attributes.class = classes_to_add;
70 | }
71 | else {
72 | attributes.class += ' ' + classes_to_add;
73 | }
74 | }
75 | if (styles_to_add) {
76 | if (attributes.style == null) {
77 | attributes.style = style_object_to_string(styles_to_add);
78 | }
79 | else {
80 | attributes.style = style_object_to_string(merge_ssr_styles(attributes.style, styles_to_add));
81 | }
82 | }
83 | }
84 | let str = '';
85 | Object.keys(attributes).forEach(name => {
86 | if (invalid_attribute_name_character.test(name))
87 | return;
88 | const value = attributes[name];
89 | if (value === true)
90 | str += ' ' + name;
91 | else if (boolean_attributes.has(name.toLowerCase())) {
92 | if (value)
93 | str += ' ' + name;
94 | }
95 | else if (value != null) {
96 | str += ` ${name}="${value}"`;
97 | }
98 | });
99 | return str;
100 | }
101 | function merge_ssr_styles(style_attribute, style_directive) {
102 | const style_object = {};
103 | for (const individual_style of style_attribute.split(';')) {
104 | const colon_index = individual_style.indexOf(':');
105 | const name = individual_style.slice(0, colon_index).trim();
106 | const value = individual_style.slice(colon_index + 1).trim();
107 | if (!name)
108 | continue;
109 | style_object[name] = value;
110 | }
111 | for (const name in style_directive) {
112 | const value = style_directive[name];
113 | if (value) {
114 | style_object[name] = value;
115 | }
116 | else {
117 | delete style_object[name];
118 | }
119 | }
120 | return style_object;
121 | }
122 | const ATTR_REGEX = /[&"]/g;
123 | const CONTENT_REGEX = /[&<]/g;
124 | /**
125 | * Note: this method is performance sensitive and has been optimized
126 | * https://github.com/sveltejs/svelte/pull/5701
127 | */
128 | function escape(value, is_attr = false) {
129 | const str = String(value);
130 | const pattern = is_attr ? ATTR_REGEX : CONTENT_REGEX;
131 | pattern.lastIndex = 0;
132 | let escaped = '';
133 | let last = 0;
134 | while (pattern.test(str)) {
135 | const i = pattern.lastIndex - 1;
136 | const ch = str[i];
137 | escaped += str.substring(last, i) + (ch === '&' ? '&' : (ch === '"' ? '"' : '<'));
138 | last = i + 1;
139 | }
140 | return escaped + str.substring(last);
141 | }
142 | function escape_attribute_value(value) {
143 | // keep booleans, null, and undefined for the sake of `spread`
144 | const should_escape = typeof value === 'string' || (value && typeof value === 'object');
145 | return should_escape ? escape(value, true) : value;
146 | }
147 | function escape_object(obj) {
148 | const result = {};
149 | for (const key in obj) {
150 | result[key] = escape_attribute_value(obj[key]);
151 | }
152 | return result;
153 | }
154 | function validate_component(component, name) {
155 | if (!component || !component.$$render) {
156 | if (name === 'svelte:component')
157 | name += ' this={...}';
158 | throw new Error(`<${name}> is not a valid SSR component. You may need to review your build config to ensure that dependencies are compiled, rather than imported as pre-compiled modules. Otherwise you may need to fix a <${name}>.`);
159 | }
160 | return component;
161 | }
162 | let on_destroy;
163 | function create_ssr_component(fn) {
164 | function $$render(result, props, bindings, slots, context) {
165 | const parent_component = current_component;
166 | const $$ = {
167 | on_destroy,
168 | context: new Map(context || (parent_component ? parent_component.$$.context : [])),
169 | // these will be immediately discarded
170 | on_mount: [],
171 | before_update: [],
172 | after_update: [],
173 | callbacks: blank_object()
174 | };
175 | set_current_component({ $$ });
176 | const html = fn(result, props, bindings, slots);
177 | set_current_component(parent_component);
178 | return html;
179 | }
180 | return {
181 | render: (props = {}, { $$slots = {}, context = new Map() } = {}) => {
182 | on_destroy = [];
183 | const result = { title: '', head: '', css: new Set() };
184 | const html = $$render(result, props, {}, $$slots, context);
185 | run_all(on_destroy);
186 | return {
187 | html,
188 | css: {
189 | code: Array.from(result.css).map(css => css.code).join('\n'),
190 | map: null // TODO
191 | },
192 | head: result.title + result.head
193 | };
194 | },
195 | $$render
196 | };
197 | }
198 | function add_attribute(name, value, boolean) {
199 | if (value == null || (boolean && !value))
200 | return '';
201 | const assignment = (boolean && value === true) ? '' : `="${escape(value, true)}"`;
202 | return ` ${name}${assignment}`;
203 | }
204 | function style_object_to_string(style_object) {
205 | return Object.keys(style_object)
206 | .filter(key => style_object[key])
207 | .map(key => `${key}: ${escape_attribute_value(style_object[key])};`)
208 | .join(' ');
209 | }
210 |
211 | // Get CSS class list from a props object
212 | function classList(props) {
213 | const {
214 | beat,
215 | fade,
216 | beatFade,
217 | bounce,
218 | shake,
219 | flash,
220 | spin,
221 | spinPulse,
222 | spinReverse,
223 | pulse,
224 | fixedWidth,
225 | inverse,
226 | border,
227 | listItem,
228 | flip,
229 | size,
230 | rotation,
231 | pull
232 | } = props;
233 |
234 | // map of CSS class names to properties
235 | const classes = {
236 | 'fa-beat': beat,
237 | 'fa-fade': fade,
238 | 'fa-beat-fade': beatFade,
239 | 'fa-bounce': bounce,
240 | 'fa-shake': shake,
241 | 'fa-flash': flash,
242 | 'fa-spin': spin,
243 | 'fa-spin-reverse': spinReverse,
244 | 'fa-spin-pulse': spinPulse,
245 | 'fa-pulse': pulse,
246 | 'fa-fw': fixedWidth,
247 | 'fa-inverse': inverse,
248 | 'fa-border': border,
249 | 'fa-li': listItem,
250 | 'fa-flip': flip === true,
251 | 'fa-flip-horizontal': flip === 'horizontal' || flip === 'both',
252 | 'fa-flip-vertical': flip === 'vertical' || flip === 'both',
253 | [`fa-${size}`]: typeof size !== 'undefined' && size !== null,
254 | [`fa-rotate-${rotation}`]:
255 | typeof rotation !== 'undefined' && rotation !== null && rotation !== 0,
256 | [`fa-pull-${pull}`]: typeof pull !== 'undefined' && pull !== null,
257 | 'fa-swap-opacity': props.swapOpacity
258 | };
259 |
260 | // map over all the keys in the classes object
261 | // return an array of the keys where the value for the key is not null
262 | return Object.keys(classes)
263 | .map(key => (classes[key] ? key : null))
264 | .filter(key => key)
265 | }
266 |
267 | // Camelize taken from humps
268 | // humps is copyright © 2012+ Dom Christie
269 | // Released under the MIT license.
270 |
271 | // Performant way to determine if object coerces to a number
272 | function _isNumerical(obj) {
273 | obj = obj - 0;
274 |
275 | // eslint-disable-next-line no-self-compare
276 | return obj === obj
277 | }
278 |
279 | function camelize(string) {
280 | if (_isNumerical(string)) {
281 | return string
282 | }
283 |
284 | // eslint-disable-next-line no-useless-escape
285 | string = string.replace(/[\-_\s]+(.)?/g, function(match, chr) {
286 | return chr ? chr.toUpperCase() : ''
287 | });
288 |
289 | // Ensure 1st char is always lowercase
290 | return string.substr(0, 1).toLowerCase() + string.substr(1)
291 | }
292 |
293 | function styleToString(style) {
294 | if (typeof style === 'string') {
295 | return style
296 | }
297 |
298 | return Object.keys(style).reduce((acc, key) => (
299 | acc + key.split(/(?=[A-Z])/).join('-').toLowerCase() + ':' + style[key] + ';'
300 | ), '')
301 | }
302 |
303 | function convert(createElement, element, extraProps = {}) {
304 | if (typeof element === 'string') {
305 | return element
306 | }
307 |
308 | const children = (element.children || []).map((child) => {
309 | return convert(createElement, child)
310 | });
311 |
312 | /* eslint-disable dot-notation */
313 | const mixins = Object.keys(element.attributes || {}).reduce(
314 | (acc, key) => {
315 | const val = element.attributes[key];
316 |
317 | if (key === 'style') {
318 | acc.attrs['style'] = styleToString(val);
319 | } else {
320 | if (key.indexOf('aria-') === 0 || key.indexOf('data-') === 0) {
321 | acc.attrs[key.toLowerCase()] = val;
322 | } else {
323 | acc.attrs[camelize(key)] = val;
324 | }
325 | }
326 |
327 | return acc
328 | },
329 | { attrs: {} }
330 | );
331 |
332 | /* eslint-enable */
333 |
334 | return createElement(element.tag, { ...mixins.attrs }, children)
335 | }
336 |
337 | let PRODUCTION = false;
338 |
339 | try {
340 | PRODUCTION = process.env.NODE_ENV === 'production';
341 | } catch (e) {}
342 |
343 | function log(...args) {
344 | if (!PRODUCTION && console && typeof console.error === 'function') {
345 | console.error(...args);
346 | }
347 | }
348 |
349 | // Normalize icon arguments
350 | function normalizeIconArgs(icon) {
351 | // this has everything that it needs to be rendered which means it was probably imported
352 | // directly from an icon svg package
353 | if (icon && typeof icon === 'object' && icon.prefix && icon.iconName && icon.icon) {
354 | return icon
355 | }
356 |
357 | if (parse.icon) {
358 | return parse.icon(icon)
359 | }
360 |
361 | // if the icon is null, there's nothing to do
362 | if (icon === null) {
363 | return null
364 | }
365 |
366 | // if the icon is an object and has a prefix and an icon name, return it
367 | if (icon && typeof icon === 'object' && icon.prefix && icon.iconName) {
368 | return icon
369 | }
370 |
371 | // if it's an array with length of two
372 | if (Array.isArray(icon) && icon.length === 2) {
373 | // use the first item as prefix, second as icon name
374 | return { prefix: icon[0], iconName: icon[1] }
375 | }
376 |
377 | // if it's a string, use it as the icon name
378 | if (typeof icon === 'string') {
379 | return { prefix: 'fas', iconName: icon }
380 | }
381 | }
382 |
383 | // creates an object with a key of key
384 | // and a value of value
385 | // if certain conditions are met
386 | function objectWithKey(key, value) {
387 | // if the value is a non-empty array
388 | // or it's not an array but it is truthy
389 | // then create the object with the key and the value
390 | // if not, return an empty array
391 | return (Array.isArray(value) && value.length > 0) ||
392 | (!Array.isArray(value) && value)
393 | ? { [key]: value }
394 | : {}
395 | }
396 |
397 | /* src/components/SvgElement.svelte generated by Svelte v3.59.2 */
398 |
399 | const SvgElement = create_ssr_component(($$result, $$props, $$bindings, slots) => {
400 | let { tag } = $$props;
401 | let { props } = $$props;
402 | let { children } = $$props;
403 | let { style = null } = $$props;
404 | let { ref = null } = $$props;
405 |
406 | if (tag !== 'svg') {
407 | throw new Error('SvgElement requires a tag of "svg"');
408 | }
409 |
410 | function processChildren(children) {
411 | return children?.reduce(
412 | (acc, child) => {
413 | return acc + (child.tag ? generateMarkup(child) : child);
414 | },
415 | ''
416 | ) || '';
417 | }
418 |
419 | function generateMarkup({ tag, props, children }) {
420 | // Generate a string setting key = value for each prop
421 | const attributes = Object.keys(props).map(key => `${key}="${props[key]}"`).join(' ');
422 |
423 | return `<${tag} ${attributes}>${processChildren(children)}${tag}>`;
424 | }
425 |
426 | const markup = processChildren(children);
427 | const elementStyle = (props?.style) ? `${props.style}${style || ''}` : style;
428 | const elementProps = { ...props, style: elementStyle };
429 | if ($$props.tag === void 0 && $$bindings.tag && tag !== void 0) $$bindings.tag(tag);
430 | if ($$props.props === void 0 && $$bindings.props && props !== void 0) $$bindings.props(props);
431 | if ($$props.children === void 0 && $$bindings.children && children !== void 0) $$bindings.children(children);
432 | if ($$props.style === void 0 && $$bindings.style && style !== void 0) $$bindings.style(style);
433 | if ($$props.ref === void 0 && $$bindings.ref && ref !== void 0) $$bindings.ref(ref);
434 | return `${markup} `;
435 | });
436 |
437 | /* src/components/FontAwesomeIcon.svelte generated by Svelte v3.59.2 */
438 |
439 | const FontAwesomeIcon = create_ssr_component(($$result, $$props, $$bindings, slots) => {
440 | let $$restProps = compute_rest_props($$props, [
441 | "border","mask","maskId","fixedWidth","inverse","flip","icon","listItem","pull","pulse","rotation","size","spin","spinPulse","spinReverse","beat","fade","beatFade","bounce","shake","symbol","title","titleId","transform","swapOpacity","ref","style"
442 | ]);
443 |
444 | let { border = false } = $$props;
445 | let { mask = null } = $$props;
446 | let { maskId = null } = $$props;
447 | let { fixedWidth = false } = $$props;
448 | let { inverse = false } = $$props;
449 | let { flip = false } = $$props;
450 | let { icon: icon$1 = null } = $$props;
451 | let { listItem = false } = $$props;
452 | let { pull = null } = $$props;
453 | let { pulse = false } = $$props;
454 | let { rotation = null } = $$props;
455 | let { size = null } = $$props;
456 | let { spin = false } = $$props;
457 | let { spinPulse = false } = $$props;
458 | let { spinReverse = false } = $$props;
459 | let { beat = false } = $$props;
460 | let { fade = false } = $$props;
461 | let { beatFade = false } = $$props;
462 | let { bounce = false } = $$props;
463 | let { shake = false } = $$props;
464 | let { symbol = false } = $$props;
465 | let { title = '' } = $$props;
466 | let { titleId = null } = $$props;
467 | let { transform = null } = $$props;
468 | let { swapOpacity = false } = $$props;
469 | let { ref = null } = $$props;
470 | let { style = null } = $$props;
471 | const iconLookup = normalizeIconArgs(icon$1);
472 | const classes = objectWithKey('classes', [...classList($$props), ...($$props.class || '').split(' ')]);
473 |
474 | const transformObj = objectWithKey('transform', typeof transform === 'string'
475 | ? parse.transform(transform)
476 | : transform);
477 |
478 | const maskObj = objectWithKey('mask', normalizeIconArgs(mask));
479 |
480 | const renderedIcon = icon(iconLookup, {
481 | ...classes,
482 | ...transformObj,
483 | ...maskObj,
484 | symbol,
485 | title,
486 | titleId,
487 | maskId
488 | });
489 |
490 | let result = null;
491 |
492 | if (!renderedIcon) {
493 | log('Could not find icon', iconLookup);
494 | } else {
495 | const { abstract } = renderedIcon;
496 |
497 | result = convert(
498 | (tag, props, children) => {
499 | return { tag, props, children };
500 | },
501 | abstract[0],
502 | $$restProps
503 | );
504 | }
505 |
506 | if ($$props.border === void 0 && $$bindings.border && border !== void 0) $$bindings.border(border);
507 | if ($$props.mask === void 0 && $$bindings.mask && mask !== void 0) $$bindings.mask(mask);
508 | if ($$props.maskId === void 0 && $$bindings.maskId && maskId !== void 0) $$bindings.maskId(maskId);
509 | if ($$props.fixedWidth === void 0 && $$bindings.fixedWidth && fixedWidth !== void 0) $$bindings.fixedWidth(fixedWidth);
510 | if ($$props.inverse === void 0 && $$bindings.inverse && inverse !== void 0) $$bindings.inverse(inverse);
511 | if ($$props.flip === void 0 && $$bindings.flip && flip !== void 0) $$bindings.flip(flip);
512 | if ($$props.icon === void 0 && $$bindings.icon && icon$1 !== void 0) $$bindings.icon(icon$1);
513 | if ($$props.listItem === void 0 && $$bindings.listItem && listItem !== void 0) $$bindings.listItem(listItem);
514 | if ($$props.pull === void 0 && $$bindings.pull && pull !== void 0) $$bindings.pull(pull);
515 | if ($$props.pulse === void 0 && $$bindings.pulse && pulse !== void 0) $$bindings.pulse(pulse);
516 | if ($$props.rotation === void 0 && $$bindings.rotation && rotation !== void 0) $$bindings.rotation(rotation);
517 | if ($$props.size === void 0 && $$bindings.size && size !== void 0) $$bindings.size(size);
518 | if ($$props.spin === void 0 && $$bindings.spin && spin !== void 0) $$bindings.spin(spin);
519 | if ($$props.spinPulse === void 0 && $$bindings.spinPulse && spinPulse !== void 0) $$bindings.spinPulse(spinPulse);
520 | if ($$props.spinReverse === void 0 && $$bindings.spinReverse && spinReverse !== void 0) $$bindings.spinReverse(spinReverse);
521 | if ($$props.beat === void 0 && $$bindings.beat && beat !== void 0) $$bindings.beat(beat);
522 | if ($$props.fade === void 0 && $$bindings.fade && fade !== void 0) $$bindings.fade(fade);
523 | if ($$props.beatFade === void 0 && $$bindings.beatFade && beatFade !== void 0) $$bindings.beatFade(beatFade);
524 | if ($$props.bounce === void 0 && $$bindings.bounce && bounce !== void 0) $$bindings.bounce(bounce);
525 | if ($$props.shake === void 0 && $$bindings.shake && shake !== void 0) $$bindings.shake(shake);
526 | if ($$props.symbol === void 0 && $$bindings.symbol && symbol !== void 0) $$bindings.symbol(symbol);
527 | if ($$props.title === void 0 && $$bindings.title && title !== void 0) $$bindings.title(title);
528 | if ($$props.titleId === void 0 && $$bindings.titleId && titleId !== void 0) $$bindings.titleId(titleId);
529 | if ($$props.transform === void 0 && $$bindings.transform && transform !== void 0) $$bindings.transform(transform);
530 | if ($$props.swapOpacity === void 0 && $$bindings.swapOpacity && swapOpacity !== void 0) $$bindings.swapOpacity(swapOpacity);
531 | if ($$props.ref === void 0 && $$bindings.ref && ref !== void 0) $$bindings.ref(ref);
532 | if ($$props.style === void 0 && $$bindings.style && style !== void 0) $$bindings.style(style);
533 | let $$settled;
534 | let $$rendered;
535 |
536 | do {
537 | $$settled = true;
538 |
539 | $$rendered = `${result
540 | ? `${validate_component(SvgElement, "SvgElement").$$render(
541 | $$result,
542 | Object.assign({}, result, { style }, { ref }),
543 | {
544 | ref: $$value => {
545 | ref = $$value;
546 | $$settled = false;
547 | }
548 | },
549 | {}
550 | )}`
551 | : ``}`;
552 | } while (!$$settled);
553 |
554 | return $$rendered;
555 | });
556 |
557 | export { FontAwesomeIcon };
558 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | (function (global, factory) {
2 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@fortawesome/fontawesome-svg-core')) :
3 | typeof define === 'function' && define.amd ? define(['exports', '@fortawesome/fontawesome-svg-core'], factory) :
4 | (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["svelte-fontawesome"] = {}, global.FontAwesome));
5 | })(this, (function (exports, fontawesomeSvgCore) { 'use strict';
6 |
7 | function run(fn) {
8 | return fn();
9 | }
10 | function blank_object() {
11 | return Object.create(null);
12 | }
13 | function run_all(fns) {
14 | fns.forEach(run);
15 | }
16 | function compute_rest_props(props, keys) {
17 | const rest = {};
18 | keys = new Set(keys);
19 | for (const k in props)
20 | if (!keys.has(k) && k[0] !== '$')
21 | rest[k] = props[k];
22 | return rest;
23 | }
24 |
25 | let current_component;
26 | function set_current_component(component) {
27 | current_component = component;
28 | }
29 |
30 | const _boolean_attributes = [
31 | 'allowfullscreen',
32 | 'allowpaymentrequest',
33 | 'async',
34 | 'autofocus',
35 | 'autoplay',
36 | 'checked',
37 | 'controls',
38 | 'default',
39 | 'defer',
40 | 'disabled',
41 | 'formnovalidate',
42 | 'hidden',
43 | 'inert',
44 | 'ismap',
45 | 'loop',
46 | 'multiple',
47 | 'muted',
48 | 'nomodule',
49 | 'novalidate',
50 | 'open',
51 | 'playsinline',
52 | 'readonly',
53 | 'required',
54 | 'reversed',
55 | 'selected'
56 | ];
57 | /**
58 | * List of HTML boolean attributes (e.g. ` `).
59 | * Source: https://html.spec.whatwg.org/multipage/indices.html
60 | */
61 | const boolean_attributes = new Set([..._boolean_attributes]);
62 |
63 | const invalid_attribute_name_character = /[\s'">/=\u{FDD0}-\u{FDEF}\u{FFFE}\u{FFFF}\u{1FFFE}\u{1FFFF}\u{2FFFE}\u{2FFFF}\u{3FFFE}\u{3FFFF}\u{4FFFE}\u{4FFFF}\u{5FFFE}\u{5FFFF}\u{6FFFE}\u{6FFFF}\u{7FFFE}\u{7FFFF}\u{8FFFE}\u{8FFFF}\u{9FFFE}\u{9FFFF}\u{AFFFE}\u{AFFFF}\u{BFFFE}\u{BFFFF}\u{CFFFE}\u{CFFFF}\u{DFFFE}\u{DFFFF}\u{EFFFE}\u{EFFFF}\u{FFFFE}\u{FFFFF}\u{10FFFE}\u{10FFFF}]/u;
64 | // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2
65 | // https://infra.spec.whatwg.org/#noncharacter
66 | function spread(args, attrs_to_add) {
67 | const attributes = Object.assign({}, ...args);
68 | if (attrs_to_add) {
69 | const classes_to_add = attrs_to_add.classes;
70 | const styles_to_add = attrs_to_add.styles;
71 | if (classes_to_add) {
72 | if (attributes.class == null) {
73 | attributes.class = classes_to_add;
74 | }
75 | else {
76 | attributes.class += ' ' + classes_to_add;
77 | }
78 | }
79 | if (styles_to_add) {
80 | if (attributes.style == null) {
81 | attributes.style = style_object_to_string(styles_to_add);
82 | }
83 | else {
84 | attributes.style = style_object_to_string(merge_ssr_styles(attributes.style, styles_to_add));
85 | }
86 | }
87 | }
88 | let str = '';
89 | Object.keys(attributes).forEach(name => {
90 | if (invalid_attribute_name_character.test(name))
91 | return;
92 | const value = attributes[name];
93 | if (value === true)
94 | str += ' ' + name;
95 | else if (boolean_attributes.has(name.toLowerCase())) {
96 | if (value)
97 | str += ' ' + name;
98 | }
99 | else if (value != null) {
100 | str += ` ${name}="${value}"`;
101 | }
102 | });
103 | return str;
104 | }
105 | function merge_ssr_styles(style_attribute, style_directive) {
106 | const style_object = {};
107 | for (const individual_style of style_attribute.split(';')) {
108 | const colon_index = individual_style.indexOf(':');
109 | const name = individual_style.slice(0, colon_index).trim();
110 | const value = individual_style.slice(colon_index + 1).trim();
111 | if (!name)
112 | continue;
113 | style_object[name] = value;
114 | }
115 | for (const name in style_directive) {
116 | const value = style_directive[name];
117 | if (value) {
118 | style_object[name] = value;
119 | }
120 | else {
121 | delete style_object[name];
122 | }
123 | }
124 | return style_object;
125 | }
126 | const ATTR_REGEX = /[&"]/g;
127 | const CONTENT_REGEX = /[&<]/g;
128 | /**
129 | * Note: this method is performance sensitive and has been optimized
130 | * https://github.com/sveltejs/svelte/pull/5701
131 | */
132 | function escape(value, is_attr = false) {
133 | const str = String(value);
134 | const pattern = is_attr ? ATTR_REGEX : CONTENT_REGEX;
135 | pattern.lastIndex = 0;
136 | let escaped = '';
137 | let last = 0;
138 | while (pattern.test(str)) {
139 | const i = pattern.lastIndex - 1;
140 | const ch = str[i];
141 | escaped += str.substring(last, i) + (ch === '&' ? '&' : (ch === '"' ? '"' : '<'));
142 | last = i + 1;
143 | }
144 | return escaped + str.substring(last);
145 | }
146 | function escape_attribute_value(value) {
147 | // keep booleans, null, and undefined for the sake of `spread`
148 | const should_escape = typeof value === 'string' || (value && typeof value === 'object');
149 | return should_escape ? escape(value, true) : value;
150 | }
151 | function escape_object(obj) {
152 | const result = {};
153 | for (const key in obj) {
154 | result[key] = escape_attribute_value(obj[key]);
155 | }
156 | return result;
157 | }
158 | function validate_component(component, name) {
159 | if (!component || !component.$$render) {
160 | if (name === 'svelte:component')
161 | name += ' this={...}';
162 | throw new Error(`<${name}> is not a valid SSR component. You may need to review your build config to ensure that dependencies are compiled, rather than imported as pre-compiled modules. Otherwise you may need to fix a <${name}>.`);
163 | }
164 | return component;
165 | }
166 | let on_destroy;
167 | function create_ssr_component(fn) {
168 | function $$render(result, props, bindings, slots, context) {
169 | const parent_component = current_component;
170 | const $$ = {
171 | on_destroy,
172 | context: new Map(context || (parent_component ? parent_component.$$.context : [])),
173 | // these will be immediately discarded
174 | on_mount: [],
175 | before_update: [],
176 | after_update: [],
177 | callbacks: blank_object()
178 | };
179 | set_current_component({ $$ });
180 | const html = fn(result, props, bindings, slots);
181 | set_current_component(parent_component);
182 | return html;
183 | }
184 | return {
185 | render: (props = {}, { $$slots = {}, context = new Map() } = {}) => {
186 | on_destroy = [];
187 | const result = { title: '', head: '', css: new Set() };
188 | const html = $$render(result, props, {}, $$slots, context);
189 | run_all(on_destroy);
190 | return {
191 | html,
192 | css: {
193 | code: Array.from(result.css).map(css => css.code).join('\n'),
194 | map: null // TODO
195 | },
196 | head: result.title + result.head
197 | };
198 | },
199 | $$render
200 | };
201 | }
202 | function add_attribute(name, value, boolean) {
203 | if (value == null || (boolean && !value))
204 | return '';
205 | const assignment = (boolean && value === true) ? '' : `="${escape(value, true)}"`;
206 | return ` ${name}${assignment}`;
207 | }
208 | function style_object_to_string(style_object) {
209 | return Object.keys(style_object)
210 | .filter(key => style_object[key])
211 | .map(key => `${key}: ${escape_attribute_value(style_object[key])};`)
212 | .join(' ');
213 | }
214 |
215 | // Get CSS class list from a props object
216 | function classList(props) {
217 | const {
218 | beat,
219 | fade,
220 | beatFade,
221 | bounce,
222 | shake,
223 | flash,
224 | spin,
225 | spinPulse,
226 | spinReverse,
227 | pulse,
228 | fixedWidth,
229 | inverse,
230 | border,
231 | listItem,
232 | flip,
233 | size,
234 | rotation,
235 | pull
236 | } = props;
237 |
238 | // map of CSS class names to properties
239 | const classes = {
240 | 'fa-beat': beat,
241 | 'fa-fade': fade,
242 | 'fa-beat-fade': beatFade,
243 | 'fa-bounce': bounce,
244 | 'fa-shake': shake,
245 | 'fa-flash': flash,
246 | 'fa-spin': spin,
247 | 'fa-spin-reverse': spinReverse,
248 | 'fa-spin-pulse': spinPulse,
249 | 'fa-pulse': pulse,
250 | 'fa-fw': fixedWidth,
251 | 'fa-inverse': inverse,
252 | 'fa-border': border,
253 | 'fa-li': listItem,
254 | 'fa-flip': flip === true,
255 | 'fa-flip-horizontal': flip === 'horizontal' || flip === 'both',
256 | 'fa-flip-vertical': flip === 'vertical' || flip === 'both',
257 | [`fa-${size}`]: typeof size !== 'undefined' && size !== null,
258 | [`fa-rotate-${rotation}`]:
259 | typeof rotation !== 'undefined' && rotation !== null && rotation !== 0,
260 | [`fa-pull-${pull}`]: typeof pull !== 'undefined' && pull !== null,
261 | 'fa-swap-opacity': props.swapOpacity
262 | };
263 |
264 | // map over all the keys in the classes object
265 | // return an array of the keys where the value for the key is not null
266 | return Object.keys(classes)
267 | .map(key => (classes[key] ? key : null))
268 | .filter(key => key)
269 | }
270 |
271 | // Camelize taken from humps
272 | // humps is copyright © 2012+ Dom Christie
273 | // Released under the MIT license.
274 |
275 | // Performant way to determine if object coerces to a number
276 | function _isNumerical(obj) {
277 | obj = obj - 0;
278 |
279 | // eslint-disable-next-line no-self-compare
280 | return obj === obj
281 | }
282 |
283 | function camelize(string) {
284 | if (_isNumerical(string)) {
285 | return string
286 | }
287 |
288 | // eslint-disable-next-line no-useless-escape
289 | string = string.replace(/[\-_\s]+(.)?/g, function(match, chr) {
290 | return chr ? chr.toUpperCase() : ''
291 | });
292 |
293 | // Ensure 1st char is always lowercase
294 | return string.substr(0, 1).toLowerCase() + string.substr(1)
295 | }
296 |
297 | function styleToString(style) {
298 | if (typeof style === 'string') {
299 | return style
300 | }
301 |
302 | return Object.keys(style).reduce((acc, key) => (
303 | acc + key.split(/(?=[A-Z])/).join('-').toLowerCase() + ':' + style[key] + ';'
304 | ), '')
305 | }
306 |
307 | function convert(createElement, element, extraProps = {}) {
308 | if (typeof element === 'string') {
309 | return element
310 | }
311 |
312 | const children = (element.children || []).map((child) => {
313 | return convert(createElement, child)
314 | });
315 |
316 | /* eslint-disable dot-notation */
317 | const mixins = Object.keys(element.attributes || {}).reduce(
318 | (acc, key) => {
319 | const val = element.attributes[key];
320 |
321 | if (key === 'style') {
322 | acc.attrs['style'] = styleToString(val);
323 | } else {
324 | if (key.indexOf('aria-') === 0 || key.indexOf('data-') === 0) {
325 | acc.attrs[key.toLowerCase()] = val;
326 | } else {
327 | acc.attrs[camelize(key)] = val;
328 | }
329 | }
330 |
331 | return acc
332 | },
333 | { attrs: {} }
334 | );
335 |
336 | /* eslint-enable */
337 |
338 | return createElement(element.tag, { ...mixins.attrs }, children)
339 | }
340 |
341 | let PRODUCTION = false;
342 |
343 | try {
344 | PRODUCTION = process.env.NODE_ENV === 'production';
345 | } catch (e) {}
346 |
347 | function log(...args) {
348 | if (!PRODUCTION && console && typeof console.error === 'function') {
349 | console.error(...args);
350 | }
351 | }
352 |
353 | // Normalize icon arguments
354 | function normalizeIconArgs(icon) {
355 | // this has everything that it needs to be rendered which means it was probably imported
356 | // directly from an icon svg package
357 | if (icon && typeof icon === 'object' && icon.prefix && icon.iconName && icon.icon) {
358 | return icon
359 | }
360 |
361 | if (fontawesomeSvgCore.parse.icon) {
362 | return fontawesomeSvgCore.parse.icon(icon)
363 | }
364 |
365 | // if the icon is null, there's nothing to do
366 | if (icon === null) {
367 | return null
368 | }
369 |
370 | // if the icon is an object and has a prefix and an icon name, return it
371 | if (icon && typeof icon === 'object' && icon.prefix && icon.iconName) {
372 | return icon
373 | }
374 |
375 | // if it's an array with length of two
376 | if (Array.isArray(icon) && icon.length === 2) {
377 | // use the first item as prefix, second as icon name
378 | return { prefix: icon[0], iconName: icon[1] }
379 | }
380 |
381 | // if it's a string, use it as the icon name
382 | if (typeof icon === 'string') {
383 | return { prefix: 'fas', iconName: icon }
384 | }
385 | }
386 |
387 | // creates an object with a key of key
388 | // and a value of value
389 | // if certain conditions are met
390 | function objectWithKey(key, value) {
391 | // if the value is a non-empty array
392 | // or it's not an array but it is truthy
393 | // then create the object with the key and the value
394 | // if not, return an empty array
395 | return (Array.isArray(value) && value.length > 0) ||
396 | (!Array.isArray(value) && value)
397 | ? { [key]: value }
398 | : {}
399 | }
400 |
401 | /* src/components/SvgElement.svelte generated by Svelte v3.59.2 */
402 |
403 | const SvgElement = create_ssr_component(($$result, $$props, $$bindings, slots) => {
404 | let { tag } = $$props;
405 | let { props } = $$props;
406 | let { children } = $$props;
407 | let { style = null } = $$props;
408 | let { ref = null } = $$props;
409 |
410 | if (tag !== 'svg') {
411 | throw new Error('SvgElement requires a tag of "svg"');
412 | }
413 |
414 | function processChildren(children) {
415 | return children?.reduce(
416 | (acc, child) => {
417 | return acc + (child.tag ? generateMarkup(child) : child);
418 | },
419 | ''
420 | ) || '';
421 | }
422 |
423 | function generateMarkup({ tag, props, children }) {
424 | // Generate a string setting key = value for each prop
425 | const attributes = Object.keys(props).map(key => `${key}="${props[key]}"`).join(' ');
426 |
427 | return `<${tag} ${attributes}>${processChildren(children)}${tag}>`;
428 | }
429 |
430 | const markup = processChildren(children);
431 | const elementStyle = (props?.style) ? `${props.style}${style || ''}` : style;
432 | const elementProps = { ...props, style: elementStyle };
433 | if ($$props.tag === void 0 && $$bindings.tag && tag !== void 0) $$bindings.tag(tag);
434 | if ($$props.props === void 0 && $$bindings.props && props !== void 0) $$bindings.props(props);
435 | if ($$props.children === void 0 && $$bindings.children && children !== void 0) $$bindings.children(children);
436 | if ($$props.style === void 0 && $$bindings.style && style !== void 0) $$bindings.style(style);
437 | if ($$props.ref === void 0 && $$bindings.ref && ref !== void 0) $$bindings.ref(ref);
438 | return `${markup} `;
439 | });
440 |
441 | /* src/components/FontAwesomeIcon.svelte generated by Svelte v3.59.2 */
442 |
443 | const FontAwesomeIcon = create_ssr_component(($$result, $$props, $$bindings, slots) => {
444 | let $$restProps = compute_rest_props($$props, [
445 | "border","mask","maskId","fixedWidth","inverse","flip","icon","listItem","pull","pulse","rotation","size","spin","spinPulse","spinReverse","beat","fade","beatFade","bounce","shake","symbol","title","titleId","transform","swapOpacity","ref","style"
446 | ]);
447 |
448 | let { border = false } = $$props;
449 | let { mask = null } = $$props;
450 | let { maskId = null } = $$props;
451 | let { fixedWidth = false } = $$props;
452 | let { inverse = false } = $$props;
453 | let { flip = false } = $$props;
454 | let { icon = null } = $$props;
455 | let { listItem = false } = $$props;
456 | let { pull = null } = $$props;
457 | let { pulse = false } = $$props;
458 | let { rotation = null } = $$props;
459 | let { size = null } = $$props;
460 | let { spin = false } = $$props;
461 | let { spinPulse = false } = $$props;
462 | let { spinReverse = false } = $$props;
463 | let { beat = false } = $$props;
464 | let { fade = false } = $$props;
465 | let { beatFade = false } = $$props;
466 | let { bounce = false } = $$props;
467 | let { shake = false } = $$props;
468 | let { symbol = false } = $$props;
469 | let { title = '' } = $$props;
470 | let { titleId = null } = $$props;
471 | let { transform = null } = $$props;
472 | let { swapOpacity = false } = $$props;
473 | let { ref = null } = $$props;
474 | let { style = null } = $$props;
475 | const iconLookup = normalizeIconArgs(icon);
476 | const classes = objectWithKey('classes', [...classList($$props), ...($$props.class || '').split(' ')]);
477 |
478 | const transformObj = objectWithKey('transform', typeof transform === 'string'
479 | ? fontawesomeSvgCore.parse.transform(transform)
480 | : transform);
481 |
482 | const maskObj = objectWithKey('mask', normalizeIconArgs(mask));
483 |
484 | const renderedIcon = fontawesomeSvgCore.icon(iconLookup, {
485 | ...classes,
486 | ...transformObj,
487 | ...maskObj,
488 | symbol,
489 | title,
490 | titleId,
491 | maskId
492 | });
493 |
494 | let result = null;
495 |
496 | if (!renderedIcon) {
497 | log('Could not find icon', iconLookup);
498 | } else {
499 | const { abstract } = renderedIcon;
500 |
501 | result = convert(
502 | (tag, props, children) => {
503 | return { tag, props, children };
504 | },
505 | abstract[0],
506 | $$restProps
507 | );
508 | }
509 |
510 | if ($$props.border === void 0 && $$bindings.border && border !== void 0) $$bindings.border(border);
511 | if ($$props.mask === void 0 && $$bindings.mask && mask !== void 0) $$bindings.mask(mask);
512 | if ($$props.maskId === void 0 && $$bindings.maskId && maskId !== void 0) $$bindings.maskId(maskId);
513 | if ($$props.fixedWidth === void 0 && $$bindings.fixedWidth && fixedWidth !== void 0) $$bindings.fixedWidth(fixedWidth);
514 | if ($$props.inverse === void 0 && $$bindings.inverse && inverse !== void 0) $$bindings.inverse(inverse);
515 | if ($$props.flip === void 0 && $$bindings.flip && flip !== void 0) $$bindings.flip(flip);
516 | if ($$props.icon === void 0 && $$bindings.icon && icon !== void 0) $$bindings.icon(icon);
517 | if ($$props.listItem === void 0 && $$bindings.listItem && listItem !== void 0) $$bindings.listItem(listItem);
518 | if ($$props.pull === void 0 && $$bindings.pull && pull !== void 0) $$bindings.pull(pull);
519 | if ($$props.pulse === void 0 && $$bindings.pulse && pulse !== void 0) $$bindings.pulse(pulse);
520 | if ($$props.rotation === void 0 && $$bindings.rotation && rotation !== void 0) $$bindings.rotation(rotation);
521 | if ($$props.size === void 0 && $$bindings.size && size !== void 0) $$bindings.size(size);
522 | if ($$props.spin === void 0 && $$bindings.spin && spin !== void 0) $$bindings.spin(spin);
523 | if ($$props.spinPulse === void 0 && $$bindings.spinPulse && spinPulse !== void 0) $$bindings.spinPulse(spinPulse);
524 | if ($$props.spinReverse === void 0 && $$bindings.spinReverse && spinReverse !== void 0) $$bindings.spinReverse(spinReverse);
525 | if ($$props.beat === void 0 && $$bindings.beat && beat !== void 0) $$bindings.beat(beat);
526 | if ($$props.fade === void 0 && $$bindings.fade && fade !== void 0) $$bindings.fade(fade);
527 | if ($$props.beatFade === void 0 && $$bindings.beatFade && beatFade !== void 0) $$bindings.beatFade(beatFade);
528 | if ($$props.bounce === void 0 && $$bindings.bounce && bounce !== void 0) $$bindings.bounce(bounce);
529 | if ($$props.shake === void 0 && $$bindings.shake && shake !== void 0) $$bindings.shake(shake);
530 | if ($$props.symbol === void 0 && $$bindings.symbol && symbol !== void 0) $$bindings.symbol(symbol);
531 | if ($$props.title === void 0 && $$bindings.title && title !== void 0) $$bindings.title(title);
532 | if ($$props.titleId === void 0 && $$bindings.titleId && titleId !== void 0) $$bindings.titleId(titleId);
533 | if ($$props.transform === void 0 && $$bindings.transform && transform !== void 0) $$bindings.transform(transform);
534 | if ($$props.swapOpacity === void 0 && $$bindings.swapOpacity && swapOpacity !== void 0) $$bindings.swapOpacity(swapOpacity);
535 | if ($$props.ref === void 0 && $$bindings.ref && ref !== void 0) $$bindings.ref(ref);
536 | if ($$props.style === void 0 && $$bindings.style && style !== void 0) $$bindings.style(style);
537 | let $$settled;
538 | let $$rendered;
539 |
540 | do {
541 | $$settled = true;
542 |
543 | $$rendered = `${result
544 | ? `${validate_component(SvgElement, "SvgElement").$$render(
545 | $$result,
546 | Object.assign({}, result, { style }, { ref }),
547 | {
548 | ref: $$value => {
549 | ref = $$value;
550 | $$settled = false;
551 | }
552 | },
553 | {}
554 | )}`
555 | : ``}`;
556 | } while (!$$settled);
557 |
558 | return $$rendered;
559 | });
560 |
561 | exports.FontAwesomeIcon = FontAwesomeIcon;
562 |
563 | Object.defineProperty(exports, '__esModule', { value: true });
564 |
565 | }));
566 |
--------------------------------------------------------------------------------
/examples/svelte-app/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "svelte-app",
3 | "version": "0.0.0",
4 | "lockfileVersion": 3,
5 | "requires": true,
6 | "packages": {
7 | "": {
8 | "name": "svelte-app",
9 | "version": "0.0.0",
10 | "devDependencies": {
11 | "@fortawesome/fontawesome-svg-core": "^7.0.0",
12 | "@fortawesome/free-brands-svg-icons": "^7.0.0",
13 | "@fortawesome/free-solid-svg-icons": "^7.0.0",
14 | "@fortawesome/svelte-fontawesome": "^0.2.0",
15 | "@sveltejs/vite-plugin-svelte": "^1.0.1",
16 | "svelte": "^3.49.0",
17 | "vite": "^3.0.0"
18 | }
19 | },
20 | "node_modules/@esbuild/android-arm": {
21 | "version": "0.15.18",
22 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.18.tgz",
23 | "integrity": "sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw==",
24 | "cpu": [
25 | "arm"
26 | ],
27 | "dev": true,
28 | "optional": true,
29 | "os": [
30 | "android"
31 | ],
32 | "engines": {
33 | "node": ">=12"
34 | }
35 | },
36 | "node_modules/@esbuild/linux-loong64": {
37 | "version": "0.15.18",
38 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.18.tgz",
39 | "integrity": "sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==",
40 | "cpu": [
41 | "loong64"
42 | ],
43 | "dev": true,
44 | "optional": true,
45 | "os": [
46 | "linux"
47 | ],
48 | "engines": {
49 | "node": ">=12"
50 | }
51 | },
52 | "node_modules/@fortawesome/fontawesome-common-types": {
53 | "version": "7.0.0",
54 | "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-7.0.0.tgz",
55 | "integrity": "sha512-PGMrIYXLGA5K8RWy8zwBkd4vFi4z7ubxtet6Yn13Plf6krRTwPbdlCwlcfmoX0R7B4Z643QvrtHmdQ5fNtfFCg==",
56 | "dev": true,
57 | "engines": {
58 | "node": ">=6"
59 | }
60 | },
61 | "node_modules/@fortawesome/fontawesome-svg-core": {
62 | "version": "7.0.0",
63 | "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-7.0.0.tgz",
64 | "integrity": "sha512-obBEF+zd98r/KtKVW6A+8UGWeaOoyMpl6Q9P3FzHsOnsg742aXsl8v+H/zp09qSSu/a/Hxe9LNKzbBaQq1CEbA==",
65 | "dev": true,
66 | "dependencies": {
67 | "@fortawesome/fontawesome-common-types": "7.0.0"
68 | },
69 | "engines": {
70 | "node": ">=6"
71 | }
72 | },
73 | "node_modules/@fortawesome/free-brands-svg-icons": {
74 | "version": "7.0.0",
75 | "resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-7.0.0.tgz",
76 | "integrity": "sha512-C8oY28gq/Qx/cHReJa2AunKJUHvUZDVoPlSTHtAvjriaNfi+5nugW4cx7yA/xN3f/nYkElw11gFBoJ2xUDDFgg==",
77 | "dev": true,
78 | "dependencies": {
79 | "@fortawesome/fontawesome-common-types": "7.0.0"
80 | },
81 | "engines": {
82 | "node": ">=6"
83 | }
84 | },
85 | "node_modules/@fortawesome/free-solid-svg-icons": {
86 | "version": "7.0.0",
87 | "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-7.0.0.tgz",
88 | "integrity": "sha512-njSLAllkOddYDCXgTFboXn54Oe5FcvpkWq+FoetOHR64PbN0608kM02Lze0xtISGpXgP+i26VyXRQA0Irh3Obw==",
89 | "dev": true,
90 | "dependencies": {
91 | "@fortawesome/fontawesome-common-types": "7.0.0"
92 | },
93 | "engines": {
94 | "node": ">=6"
95 | }
96 | },
97 | "node_modules/@fortawesome/svelte-fontawesome": {
98 | "version": "0.2.1",
99 | "resolved": "https://registry.npmjs.org/@fortawesome/svelte-fontawesome/-/svelte-fontawesome-0.2.1.tgz",
100 | "integrity": "sha512-GDGMow2poIHaT0y02EcMDAjWSy0OYbY0BLORDRp5eZBh8EckFyNvMjhTgWsTp4b/gyWrP9jNRYOXVaWAQFnK3g==",
101 | "dev": true,
102 | "peerDependencies": {
103 | "@fortawesome/fontawesome-svg-core": "~1 || ~6",
104 | "svelte": ">=3.x"
105 | }
106 | },
107 | "node_modules/@sveltejs/vite-plugin-svelte": {
108 | "version": "1.4.0",
109 | "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-1.4.0.tgz",
110 | "integrity": "sha512-6QupI/jemMfK+yI2pMtJcu5iO2gtgTfcBdGwMZZt+lgbFELhszbDl6Qjh000HgAV8+XUA+8EY8DusOFk8WhOIg==",
111 | "dev": true,
112 | "dependencies": {
113 | "debug": "^4.3.4",
114 | "deepmerge": "^4.2.2",
115 | "kleur": "^4.1.5",
116 | "magic-string": "^0.26.7",
117 | "svelte-hmr": "^0.15.1",
118 | "vitefu": "^0.2.2"
119 | },
120 | "engines": {
121 | "node": "^14.18.0 || >= 16"
122 | },
123 | "peerDependencies": {
124 | "svelte": "^3.44.0",
125 | "vite": "^3.0.0"
126 | }
127 | },
128 | "node_modules/debug": {
129 | "version": "4.3.4",
130 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
131 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
132 | "dev": true,
133 | "dependencies": {
134 | "ms": "2.1.2"
135 | },
136 | "engines": {
137 | "node": ">=6.0"
138 | },
139 | "peerDependenciesMeta": {
140 | "supports-color": {
141 | "optional": true
142 | }
143 | }
144 | },
145 | "node_modules/deepmerge": {
146 | "version": "4.3.1",
147 | "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
148 | "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
149 | "dev": true,
150 | "engines": {
151 | "node": ">=0.10.0"
152 | }
153 | },
154 | "node_modules/esbuild": {
155 | "version": "0.15.18",
156 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.18.tgz",
157 | "integrity": "sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q==",
158 | "dev": true,
159 | "hasInstallScript": true,
160 | "bin": {
161 | "esbuild": "bin/esbuild"
162 | },
163 | "engines": {
164 | "node": ">=12"
165 | },
166 | "optionalDependencies": {
167 | "@esbuild/android-arm": "0.15.18",
168 | "@esbuild/linux-loong64": "0.15.18",
169 | "esbuild-android-64": "0.15.18",
170 | "esbuild-android-arm64": "0.15.18",
171 | "esbuild-darwin-64": "0.15.18",
172 | "esbuild-darwin-arm64": "0.15.18",
173 | "esbuild-freebsd-64": "0.15.18",
174 | "esbuild-freebsd-arm64": "0.15.18",
175 | "esbuild-linux-32": "0.15.18",
176 | "esbuild-linux-64": "0.15.18",
177 | "esbuild-linux-arm": "0.15.18",
178 | "esbuild-linux-arm64": "0.15.18",
179 | "esbuild-linux-mips64le": "0.15.18",
180 | "esbuild-linux-ppc64le": "0.15.18",
181 | "esbuild-linux-riscv64": "0.15.18",
182 | "esbuild-linux-s390x": "0.15.18",
183 | "esbuild-netbsd-64": "0.15.18",
184 | "esbuild-openbsd-64": "0.15.18",
185 | "esbuild-sunos-64": "0.15.18",
186 | "esbuild-windows-32": "0.15.18",
187 | "esbuild-windows-64": "0.15.18",
188 | "esbuild-windows-arm64": "0.15.18"
189 | }
190 | },
191 | "node_modules/esbuild-android-64": {
192 | "version": "0.15.18",
193 | "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.18.tgz",
194 | "integrity": "sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==",
195 | "cpu": [
196 | "x64"
197 | ],
198 | "dev": true,
199 | "optional": true,
200 | "os": [
201 | "android"
202 | ],
203 | "engines": {
204 | "node": ">=12"
205 | }
206 | },
207 | "node_modules/esbuild-android-arm64": {
208 | "version": "0.15.18",
209 | "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.18.tgz",
210 | "integrity": "sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==",
211 | "cpu": [
212 | "arm64"
213 | ],
214 | "dev": true,
215 | "optional": true,
216 | "os": [
217 | "android"
218 | ],
219 | "engines": {
220 | "node": ">=12"
221 | }
222 | },
223 | "node_modules/esbuild-darwin-64": {
224 | "version": "0.15.18",
225 | "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.18.tgz",
226 | "integrity": "sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==",
227 | "cpu": [
228 | "x64"
229 | ],
230 | "dev": true,
231 | "optional": true,
232 | "os": [
233 | "darwin"
234 | ],
235 | "engines": {
236 | "node": ">=12"
237 | }
238 | },
239 | "node_modules/esbuild-darwin-arm64": {
240 | "version": "0.15.18",
241 | "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.18.tgz",
242 | "integrity": "sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==",
243 | "cpu": [
244 | "arm64"
245 | ],
246 | "dev": true,
247 | "optional": true,
248 | "os": [
249 | "darwin"
250 | ],
251 | "engines": {
252 | "node": ">=12"
253 | }
254 | },
255 | "node_modules/esbuild-freebsd-64": {
256 | "version": "0.15.18",
257 | "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.18.tgz",
258 | "integrity": "sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==",
259 | "cpu": [
260 | "x64"
261 | ],
262 | "dev": true,
263 | "optional": true,
264 | "os": [
265 | "freebsd"
266 | ],
267 | "engines": {
268 | "node": ">=12"
269 | }
270 | },
271 | "node_modules/esbuild-freebsd-arm64": {
272 | "version": "0.15.18",
273 | "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.18.tgz",
274 | "integrity": "sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==",
275 | "cpu": [
276 | "arm64"
277 | ],
278 | "dev": true,
279 | "optional": true,
280 | "os": [
281 | "freebsd"
282 | ],
283 | "engines": {
284 | "node": ">=12"
285 | }
286 | },
287 | "node_modules/esbuild-linux-32": {
288 | "version": "0.15.18",
289 | "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.18.tgz",
290 | "integrity": "sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==",
291 | "cpu": [
292 | "ia32"
293 | ],
294 | "dev": true,
295 | "optional": true,
296 | "os": [
297 | "linux"
298 | ],
299 | "engines": {
300 | "node": ">=12"
301 | }
302 | },
303 | "node_modules/esbuild-linux-64": {
304 | "version": "0.15.18",
305 | "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.18.tgz",
306 | "integrity": "sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==",
307 | "cpu": [
308 | "x64"
309 | ],
310 | "dev": true,
311 | "optional": true,
312 | "os": [
313 | "linux"
314 | ],
315 | "engines": {
316 | "node": ">=12"
317 | }
318 | },
319 | "node_modules/esbuild-linux-arm": {
320 | "version": "0.15.18",
321 | "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.18.tgz",
322 | "integrity": "sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==",
323 | "cpu": [
324 | "arm"
325 | ],
326 | "dev": true,
327 | "optional": true,
328 | "os": [
329 | "linux"
330 | ],
331 | "engines": {
332 | "node": ">=12"
333 | }
334 | },
335 | "node_modules/esbuild-linux-arm64": {
336 | "version": "0.15.18",
337 | "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.18.tgz",
338 | "integrity": "sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==",
339 | "cpu": [
340 | "arm64"
341 | ],
342 | "dev": true,
343 | "optional": true,
344 | "os": [
345 | "linux"
346 | ],
347 | "engines": {
348 | "node": ">=12"
349 | }
350 | },
351 | "node_modules/esbuild-linux-mips64le": {
352 | "version": "0.15.18",
353 | "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.18.tgz",
354 | "integrity": "sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==",
355 | "cpu": [
356 | "mips64el"
357 | ],
358 | "dev": true,
359 | "optional": true,
360 | "os": [
361 | "linux"
362 | ],
363 | "engines": {
364 | "node": ">=12"
365 | }
366 | },
367 | "node_modules/esbuild-linux-ppc64le": {
368 | "version": "0.15.18",
369 | "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.18.tgz",
370 | "integrity": "sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==",
371 | "cpu": [
372 | "ppc64"
373 | ],
374 | "dev": true,
375 | "optional": true,
376 | "os": [
377 | "linux"
378 | ],
379 | "engines": {
380 | "node": ">=12"
381 | }
382 | },
383 | "node_modules/esbuild-linux-riscv64": {
384 | "version": "0.15.18",
385 | "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.18.tgz",
386 | "integrity": "sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==",
387 | "cpu": [
388 | "riscv64"
389 | ],
390 | "dev": true,
391 | "optional": true,
392 | "os": [
393 | "linux"
394 | ],
395 | "engines": {
396 | "node": ">=12"
397 | }
398 | },
399 | "node_modules/esbuild-linux-s390x": {
400 | "version": "0.15.18",
401 | "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.18.tgz",
402 | "integrity": "sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==",
403 | "cpu": [
404 | "s390x"
405 | ],
406 | "dev": true,
407 | "optional": true,
408 | "os": [
409 | "linux"
410 | ],
411 | "engines": {
412 | "node": ">=12"
413 | }
414 | },
415 | "node_modules/esbuild-netbsd-64": {
416 | "version": "0.15.18",
417 | "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.18.tgz",
418 | "integrity": "sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==",
419 | "cpu": [
420 | "x64"
421 | ],
422 | "dev": true,
423 | "optional": true,
424 | "os": [
425 | "netbsd"
426 | ],
427 | "engines": {
428 | "node": ">=12"
429 | }
430 | },
431 | "node_modules/esbuild-openbsd-64": {
432 | "version": "0.15.18",
433 | "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.18.tgz",
434 | "integrity": "sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==",
435 | "cpu": [
436 | "x64"
437 | ],
438 | "dev": true,
439 | "optional": true,
440 | "os": [
441 | "openbsd"
442 | ],
443 | "engines": {
444 | "node": ">=12"
445 | }
446 | },
447 | "node_modules/esbuild-sunos-64": {
448 | "version": "0.15.18",
449 | "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.18.tgz",
450 | "integrity": "sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==",
451 | "cpu": [
452 | "x64"
453 | ],
454 | "dev": true,
455 | "optional": true,
456 | "os": [
457 | "sunos"
458 | ],
459 | "engines": {
460 | "node": ">=12"
461 | }
462 | },
463 | "node_modules/esbuild-windows-32": {
464 | "version": "0.15.18",
465 | "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.18.tgz",
466 | "integrity": "sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==",
467 | "cpu": [
468 | "ia32"
469 | ],
470 | "dev": true,
471 | "optional": true,
472 | "os": [
473 | "win32"
474 | ],
475 | "engines": {
476 | "node": ">=12"
477 | }
478 | },
479 | "node_modules/esbuild-windows-64": {
480 | "version": "0.15.18",
481 | "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.18.tgz",
482 | "integrity": "sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==",
483 | "cpu": [
484 | "x64"
485 | ],
486 | "dev": true,
487 | "optional": true,
488 | "os": [
489 | "win32"
490 | ],
491 | "engines": {
492 | "node": ">=12"
493 | }
494 | },
495 | "node_modules/esbuild-windows-arm64": {
496 | "version": "0.15.18",
497 | "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.18.tgz",
498 | "integrity": "sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==",
499 | "cpu": [
500 | "arm64"
501 | ],
502 | "dev": true,
503 | "optional": true,
504 | "os": [
505 | "win32"
506 | ],
507 | "engines": {
508 | "node": ">=12"
509 | }
510 | },
511 | "node_modules/fsevents": {
512 | "version": "2.3.3",
513 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
514 | "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
515 | "dev": true,
516 | "hasInstallScript": true,
517 | "optional": true,
518 | "os": [
519 | "darwin"
520 | ],
521 | "engines": {
522 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
523 | }
524 | },
525 | "node_modules/function-bind": {
526 | "version": "1.1.2",
527 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
528 | "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
529 | "dev": true,
530 | "funding": {
531 | "url": "https://github.com/sponsors/ljharb"
532 | }
533 | },
534 | "node_modules/hasown": {
535 | "version": "2.0.0",
536 | "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz",
537 | "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==",
538 | "dev": true,
539 | "dependencies": {
540 | "function-bind": "^1.1.2"
541 | },
542 | "engines": {
543 | "node": ">= 0.4"
544 | }
545 | },
546 | "node_modules/is-core-module": {
547 | "version": "2.13.1",
548 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz",
549 | "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==",
550 | "dev": true,
551 | "dependencies": {
552 | "hasown": "^2.0.0"
553 | },
554 | "funding": {
555 | "url": "https://github.com/sponsors/ljharb"
556 | }
557 | },
558 | "node_modules/kleur": {
559 | "version": "4.1.5",
560 | "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
561 | "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==",
562 | "dev": true,
563 | "engines": {
564 | "node": ">=6"
565 | }
566 | },
567 | "node_modules/magic-string": {
568 | "version": "0.26.7",
569 | "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.26.7.tgz",
570 | "integrity": "sha512-hX9XH3ziStPoPhJxLq1syWuZMxbDvGNbVchfrdCtanC7D13888bMFow61x8axrx+GfHLtVeAx2kxL7tTGRl+Ow==",
571 | "dev": true,
572 | "dependencies": {
573 | "sourcemap-codec": "^1.4.8"
574 | },
575 | "engines": {
576 | "node": ">=12"
577 | }
578 | },
579 | "node_modules/ms": {
580 | "version": "2.1.2",
581 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
582 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
583 | "dev": true
584 | },
585 | "node_modules/nanoid": {
586 | "version": "3.3.7",
587 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
588 | "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
589 | "dev": true,
590 | "funding": [
591 | {
592 | "type": "github",
593 | "url": "https://github.com/sponsors/ai"
594 | }
595 | ],
596 | "bin": {
597 | "nanoid": "bin/nanoid.cjs"
598 | },
599 | "engines": {
600 | "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
601 | }
602 | },
603 | "node_modules/path-parse": {
604 | "version": "1.0.7",
605 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
606 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
607 | "dev": true
608 | },
609 | "node_modules/picocolors": {
610 | "version": "1.0.0",
611 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
612 | "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
613 | "dev": true
614 | },
615 | "node_modules/postcss": {
616 | "version": "8.4.33",
617 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.33.tgz",
618 | "integrity": "sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==",
619 | "dev": true,
620 | "funding": [
621 | {
622 | "type": "opencollective",
623 | "url": "https://opencollective.com/postcss/"
624 | },
625 | {
626 | "type": "tidelift",
627 | "url": "https://tidelift.com/funding/github/npm/postcss"
628 | },
629 | {
630 | "type": "github",
631 | "url": "https://github.com/sponsors/ai"
632 | }
633 | ],
634 | "dependencies": {
635 | "nanoid": "^3.3.7",
636 | "picocolors": "^1.0.0",
637 | "source-map-js": "^1.0.2"
638 | },
639 | "engines": {
640 | "node": "^10 || ^12 || >=14"
641 | }
642 | },
643 | "node_modules/resolve": {
644 | "version": "1.22.8",
645 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
646 | "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
647 | "dev": true,
648 | "dependencies": {
649 | "is-core-module": "^2.13.0",
650 | "path-parse": "^1.0.7",
651 | "supports-preserve-symlinks-flag": "^1.0.0"
652 | },
653 | "bin": {
654 | "resolve": "bin/resolve"
655 | },
656 | "funding": {
657 | "url": "https://github.com/sponsors/ljharb"
658 | }
659 | },
660 | "node_modules/rollup": {
661 | "version": "2.79.1",
662 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz",
663 | "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==",
664 | "dev": true,
665 | "bin": {
666 | "rollup": "dist/bin/rollup"
667 | },
668 | "engines": {
669 | "node": ">=10.0.0"
670 | },
671 | "optionalDependencies": {
672 | "fsevents": "~2.3.2"
673 | }
674 | },
675 | "node_modules/source-map-js": {
676 | "version": "1.0.2",
677 | "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
678 | "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
679 | "dev": true,
680 | "engines": {
681 | "node": ">=0.10.0"
682 | }
683 | },
684 | "node_modules/sourcemap-codec": {
685 | "version": "1.4.8",
686 | "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
687 | "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==",
688 | "deprecated": "Please use @jridgewell/sourcemap-codec instead",
689 | "dev": true
690 | },
691 | "node_modules/supports-preserve-symlinks-flag": {
692 | "version": "1.0.0",
693 | "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
694 | "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
695 | "dev": true,
696 | "engines": {
697 | "node": ">= 0.4"
698 | },
699 | "funding": {
700 | "url": "https://github.com/sponsors/ljharb"
701 | }
702 | },
703 | "node_modules/svelte": {
704 | "version": "3.59.2",
705 | "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.59.2.tgz",
706 | "integrity": "sha512-vzSyuGr3eEoAtT/A6bmajosJZIUWySzY2CzB3w2pgPvnkUjGqlDnsNnA0PMO+mMAhuyMul6C2uuZzY6ELSkzyA==",
707 | "dev": true,
708 | "engines": {
709 | "node": ">= 8"
710 | }
711 | },
712 | "node_modules/svelte-hmr": {
713 | "version": "0.15.3",
714 | "resolved": "https://registry.npmjs.org/svelte-hmr/-/svelte-hmr-0.15.3.tgz",
715 | "integrity": "sha512-41snaPswvSf8TJUhlkoJBekRrABDXDMdpNpT2tfHIv4JuhgvHqLMhEPGtaQn0BmbNSTkuz2Ed20DF2eHw0SmBQ==",
716 | "dev": true,
717 | "engines": {
718 | "node": "^12.20 || ^14.13.1 || >= 16"
719 | },
720 | "peerDependencies": {
721 | "svelte": "^3.19.0 || ^4.0.0"
722 | }
723 | },
724 | "node_modules/vite": {
725 | "version": "3.2.8",
726 | "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.8.tgz",
727 | "integrity": "sha512-EtQU16PLIJpAZol2cTLttNP1mX6L0SyI0pgQB1VOoWeQnMSvtiwovV3D6NcjN8CZQWWyESD2v5NGnpz5RvgOZA==",
728 | "dev": true,
729 | "dependencies": {
730 | "esbuild": "^0.15.9",
731 | "postcss": "^8.4.18",
732 | "resolve": "^1.22.1",
733 | "rollup": "^2.79.1"
734 | },
735 | "bin": {
736 | "vite": "bin/vite.js"
737 | },
738 | "engines": {
739 | "node": "^14.18.0 || >=16.0.0"
740 | },
741 | "optionalDependencies": {
742 | "fsevents": "~2.3.2"
743 | },
744 | "peerDependencies": {
745 | "@types/node": ">= 14",
746 | "less": "*",
747 | "sass": "*",
748 | "stylus": "*",
749 | "sugarss": "*",
750 | "terser": "^5.4.0"
751 | },
752 | "peerDependenciesMeta": {
753 | "@types/node": {
754 | "optional": true
755 | },
756 | "less": {
757 | "optional": true
758 | },
759 | "sass": {
760 | "optional": true
761 | },
762 | "stylus": {
763 | "optional": true
764 | },
765 | "sugarss": {
766 | "optional": true
767 | },
768 | "terser": {
769 | "optional": true
770 | }
771 | }
772 | },
773 | "node_modules/vitefu": {
774 | "version": "0.2.5",
775 | "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-0.2.5.tgz",
776 | "integrity": "sha512-SgHtMLoqaeeGnd2evZ849ZbACbnwQCIwRH57t18FxcXoZop0uQu0uzlIhJBlF/eWVzuce0sHeqPcDo+evVcg8Q==",
777 | "dev": true,
778 | "peerDependencies": {
779 | "vite": "^3.0.0 || ^4.0.0 || ^5.0.0"
780 | },
781 | "peerDependenciesMeta": {
782 | "vite": {
783 | "optional": true
784 | }
785 | }
786 | }
787 | }
788 | }
789 |
--------------------------------------------------------------------------------