diff --git a/.eslintignore b/.eslintignore
index fc58645..ea1f53a 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -1,3 +1,4 @@
node_modules
dist
*.snap
+docs/.vitepress/cache
diff --git a/.gitignore b/.gitignore
index 0738cb5..6e4468c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
node_modules
.DS_Store
-dist
\ No newline at end of file
+dist
+docs/.vitepress/cache
\ No newline at end of file
diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts
new file mode 100644
index 0000000..6bec259
--- /dev/null
+++ b/docs/.vitepress/config.ts
@@ -0,0 +1,45 @@
+import { defineConfig } from 'vitepress'
+import Unfonts from '../../src/vite'
+
+export default defineConfig({
+ base: '/unplugin-fonts/',
+ // site-level options
+ title: 'VitePress',
+ description: 'Just playing around.',
+
+ themeConfig: {
+ // theme-level options
+ },
+
+ vite: {
+ plugins: [
+ Unfonts({
+ google: {
+ families: ['Crimson Pro', 'Open Sans', 'Material+Icons'],
+ },
+
+ custom: {
+ display: 'swap',
+ families: {
+ 'Dancing Script': './public/assets/fonts/DancingScript*',
+ },
+ },
+
+ fontsource: {
+ families: [
+ {
+ name: 'ABeeZee',
+ weights: [400],
+ styles: ['italic'],
+ },
+ {
+ name: 'Truculenta',
+ weights: [400, 700],
+ subset: 'latin-ext',
+ },
+ ],
+ },
+ }),
+ ],
+ },
+})
diff --git a/docs/.vitepress/theme/custom.css b/docs/.vitepress/theme/custom.css
new file mode 100644
index 0000000..b86d644
--- /dev/null
+++ b/docs/.vitepress/theme/custom.css
@@ -0,0 +1,6 @@
+
+:root {
+ /* --vp-font-family-base: "ABeeZee", sans-serif !important; */
+ /* --vp-font-family-base: "Crimson Pro", sans-serif !important; */
+ --vp-font-family-base: "Dancing Script", sans-serif !important;
+}
\ No newline at end of file
diff --git a/docs/.vitepress/theme/index.ts b/docs/.vitepress/theme/index.ts
new file mode 100644
index 0000000..ba9c0f3
--- /dev/null
+++ b/docs/.vitepress/theme/index.ts
@@ -0,0 +1,6 @@
+// @ts-expect-error - not typed in vitepress 60
+import DefaultTheme from 'vitepress/theme-without-fonts'
+import './custom.css'
+import 'unfonts.css'
+
+export default DefaultTheme
diff --git a/docs/index.md b/docs/index.md
new file mode 100644
index 0000000..63e443b
--- /dev/null
+++ b/docs/index.md
@@ -0,0 +1,23 @@
+---
+layout: home
+
+hero:
+ name: VitePress
+ text: Just playing around.
+ tagline: My great project tagline
+ actions:
+ - theme: brand
+ text: Markdown Examples
+ link: /markdown-examples
+ - theme: alt
+ text: API Examples
+ link: /api-examples
+
+features:
+ - title: Feature A
+ details: Lorem ipsum dolor sit amet, consectetur adipiscing elit
+ - title: Feature B
+ details: Lorem ipsum dolor sit amet, consectetur adipiscing elit
+ - title: Feature C
+ details: Lorem ipsum dolor sit amet, consectetur adipiscing elit
+---
\ No newline at end of file
diff --git a/docs/package.json b/docs/package.json
new file mode 100644
index 0000000..930f0a4
--- /dev/null
+++ b/docs/package.json
@@ -0,0 +1,15 @@
+{
+ "name": "docs",
+ "private": true,
+ "scripts": {
+ "dev": "vitepress dev",
+ "start": "vitepress dev",
+ "build": "vitepress build",
+ "preview": "vitepress preview"
+ },
+ "devDependencies": {
+ "unplugin-fonts": "workspace:*",
+ "vitepress": "^1.0.0-alpha.60"
+ }
+
+}
diff --git a/docs/public/assets/fonts/DancingScript-Bold.ttf b/docs/public/assets/fonts/DancingScript-Bold.ttf
new file mode 100644
index 0000000..49d8f3f
Binary files /dev/null and b/docs/public/assets/fonts/DancingScript-Bold.ttf differ
diff --git a/docs/public/assets/fonts/DancingScript-Medium.ttf b/docs/public/assets/fonts/DancingScript-Medium.ttf
new file mode 100644
index 0000000..fdfd690
Binary files /dev/null and b/docs/public/assets/fonts/DancingScript-Medium.ttf differ
diff --git a/docs/public/assets/fonts/DancingScript-Regular.ttf b/docs/public/assets/fonts/DancingScript-Regular.ttf
new file mode 100644
index 0000000..b215107
Binary files /dev/null and b/docs/public/assets/fonts/DancingScript-Regular.ttf differ
diff --git a/docs/public/assets/fonts/DancingScript-SemiBold.ttf b/docs/public/assets/fonts/DancingScript-SemiBold.ttf
new file mode 100644
index 0000000..ce588e1
Binary files /dev/null and b/docs/public/assets/fonts/DancingScript-SemiBold.ttf differ
diff --git a/examples/nuxt/nuxt.config.ts b/examples/nuxt/nuxt.config.ts
index 30dcb7d..00389a2 100644
--- a/examples/nuxt/nuxt.config.ts
+++ b/examples/nuxt/nuxt.config.ts
@@ -15,5 +15,5 @@ export default defineNuxtConfig({
'Dancing Script': './assets/fonts/DancingScript*',
},
},
- }
+ },
})
diff --git a/examples/nuxt/tsconfig.json b/examples/nuxt/tsconfig.json
index 28b66c5..a746f2a 100644
--- a/examples/nuxt/tsconfig.json
+++ b/examples/nuxt/tsconfig.json
@@ -1,4 +1,4 @@
{
// https://nuxt.com/docs/guide/concepts/typescript
"extends": "./.nuxt/tsconfig.json"
-}
\ No newline at end of file
+}
diff --git a/examples/vite/package.json b/examples/vite/package.json
index 7943a85..d16b3b2 100644
--- a/examples/vite/package.json
+++ b/examples/vite/package.json
@@ -7,9 +7,9 @@
"preview": "vite preview"
},
"devDependencies": {
- "vite": "^4.2.0",
- "unplugin-fonts": "workspace:*",
"@fontsource/abeezee": "^4.5.10",
- "@fontsource/truculenta": "^4.5.12"
+ "@fontsource/truculenta": "^4.5.12",
+ "unplugin-fonts": "workspace:*",
+ "vite": "^4.2.0"
}
}
diff --git a/examples/vite/vite.config.ts b/examples/vite/vite.config.ts
index d386c96..f639f74 100644
--- a/examples/vite/vite.config.ts
+++ b/examples/vite/vite.config.ts
@@ -11,7 +11,15 @@ export default defineConfig({
custom: {
display: 'swap',
families: {
- 'Dancing Script': './assets/fonts/DancingScript*',
+ 'Dancing Script': {
+ src: './assets/fonts/DancingScript*',
+ transform(font) {
+ if (font.basename === 'DancingScript-Bold')
+ font.weight = 700
+
+ return font
+ },
+ },
},
},
diff --git a/package.json b/package.json
index d4a48ae..13b3da3 100644
--- a/package.json
+++ b/package.json
@@ -75,8 +75,11 @@
"build:fix": "esno scripts/postbuild.ts",
"example:dev": "npm -C examples/vite run dev",
"example:build": "npm -C examples/vite run build",
+ "docs:dev": "npm -C docs run dev",
+ "docs:build": "npm -C docs run build",
"lint": "eslint .",
- "lint:fix": "eslint --fix ."
+ "lint:fix": "eslint --fix .",
+ "test": "vitest"
},
"peerDependencies": {
"@nuxt/kit": "^3.0.0",
@@ -97,6 +100,7 @@
"@types/node": "^18.15.3",
"@typescript-eslint/eslint-plugin": "^5.55.0",
"chalk": "^5.2.0",
+ "defu": "^6.1.2",
"eslint": "^8.36.0",
"eslint-plugin-eslint-comments": "^3.2.0",
"esno": "^0.16.3",
@@ -105,6 +109,7 @@
"tsup": "^6.6.3",
"typescript": "^5.0.2",
"vite": "^4.2.0",
+ "vitest": "^0.29.3",
"webpack": "^5.76.2"
}
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 092b502..406d8ea 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -9,6 +9,7 @@ importers:
'@types/node': ^18.15.3
'@typescript-eslint/eslint-plugin': ^5.55.0
chalk: ^5.2.0
+ defu: ^6.1.2
eslint: ^8.36.0
eslint-plugin-eslint-comments: ^3.2.0
esno: ^0.16.3
@@ -19,6 +20,7 @@ importers:
typescript: ^5.0.2
unplugin: ^1.3.1
vite: ^4.2.0
+ vitest: ^0.29.3
webpack: ^5.76.2
dependencies:
fast-glob: 3.2.12
@@ -29,6 +31,7 @@ importers:
'@types/node': 18.15.3
'@typescript-eslint/eslint-plugin': 5.55.0_j4766f7ecgqbon3u7zlxn5zszu
chalk: 5.2.0
+ defu: 6.1.2
eslint: 8.36.0
eslint-plugin-eslint-comments: 3.2.0_eslint@8.36.0
esno: 0.16.3
@@ -37,8 +40,17 @@ importers:
tsup: 6.6.3_typescript@5.0.2
typescript: 5.0.2
vite: 4.2.0_@types+node@18.15.3
+ vitest: 0.29.3
webpack: 5.76.2
+ docs:
+ specifiers:
+ unplugin-fonts: workspace:*
+ vitepress: ^1.0.0-alpha.60
+ devDependencies:
+ unplugin-fonts: link:..
+ vitepress: 1.0.0-alpha.60
+
examples/astro:
specifiers:
astro: ^2.1.3
@@ -69,6 +81,116 @@ importers:
packages:
+ /@algolia/autocomplete-core/1.7.4:
+ resolution: {integrity: sha512-daoLpQ3ps/VTMRZDEBfU8ixXd+amZcNJ4QSP3IERGyzqnL5Ch8uSRFt/4G8pUvW9c3o6GA4vtVv4I4lmnkdXyg==}
+ dependencies:
+ '@algolia/autocomplete-shared': 1.7.4
+ dev: true
+
+ /@algolia/autocomplete-preset-algolia/1.7.4_algoliasearch@4.15.0:
+ resolution: {integrity: sha512-s37hrvLEIfcmKY8VU9LsAXgm2yfmkdHT3DnA3SgHaY93yjZ2qL57wzb5QweVkYuEBZkT2PIREvRoLXC2sxTbpQ==}
+ peerDependencies:
+ '@algolia/client-search': '>= 4.9.1 < 6'
+ algoliasearch: '>= 4.9.1 < 6'
+ dependencies:
+ '@algolia/autocomplete-shared': 1.7.4
+ algoliasearch: 4.15.0
+ dev: true
+
+ /@algolia/autocomplete-shared/1.7.4:
+ resolution: {integrity: sha512-2VGCk7I9tA9Ge73Km99+Qg87w0wzW4tgUruvWAn/gfey1ZXgmxZtyIRBebk35R1O8TbK77wujVtCnpsGpRy1kg==}
+ dev: true
+
+ /@algolia/cache-browser-local-storage/4.15.0:
+ resolution: {integrity: sha512-uxxFhTWh4JJDb2+FFSmNMfEQ8p9o2vjSpU7iW007QX3OvqljPPN68lk3bpZVaG8pwr5MU1DqpkZ71FcQdVTjgQ==}
+ dependencies:
+ '@algolia/cache-common': 4.15.0
+ dev: true
+
+ /@algolia/cache-common/4.15.0:
+ resolution: {integrity: sha512-Me3PbI4QurAM+3D+htIE0l1xt6+bl/18SG6Wc7bPQEZAtN7DTGz22HqhKNyLF2lR/cOfpaH7umXZlZEhIHf7gQ==}
+ dev: true
+
+ /@algolia/cache-in-memory/4.15.0:
+ resolution: {integrity: sha512-B9mg1wd7CKMfpkbiTQ8KlcKkH6ut/goVaI6XmDCUczOOqeuZlV34tuEi7o3Xo1j66KWr/d9pMjjGYcoVPCVeOA==}
+ dependencies:
+ '@algolia/cache-common': 4.15.0
+ dev: true
+
+ /@algolia/client-account/4.15.0:
+ resolution: {integrity: sha512-8wqI33HRZy5ydfFt6F5vMhtkOiAUhVfSCYXx4U3Go5RALqWLgVUp6wzOo0mr1z08POCkHDpbQMQvyayb1CZ/kw==}
+ dependencies:
+ '@algolia/client-common': 4.15.0
+ '@algolia/client-search': 4.15.0
+ '@algolia/transporter': 4.15.0
+ dev: true
+
+ /@algolia/client-analytics/4.15.0:
+ resolution: {integrity: sha512-jrPjEeNEIIQKeA1XCZXx3f3aybtwF7wjYlnfHbLARuZ9AuHzimOKjX0ZwqvMmvTsHivpcZ2rqY+j1E8HoH1ELA==}
+ dependencies:
+ '@algolia/client-common': 4.15.0
+ '@algolia/client-search': 4.15.0
+ '@algolia/requester-common': 4.15.0
+ '@algolia/transporter': 4.15.0
+ dev: true
+
+ /@algolia/client-common/4.15.0:
+ resolution: {integrity: sha512-PlsJMObZuYw4JlG5EhYv1PHDOv7n5mD5PzqFyoNfSOYaEPRZepa3W579ya29yOu3FZ0VGMNJmB7Q5v/+/fwvIw==}
+ dependencies:
+ '@algolia/requester-common': 4.15.0
+ '@algolia/transporter': 4.15.0
+ dev: true
+
+ /@algolia/client-personalization/4.15.0:
+ resolution: {integrity: sha512-Bf0bhRAiNL9LWurzyHRH8UBi4fDt3VbCNkInxVngKQT1uCZWXecwoPWGhcSSpdanBqFJA/1WBt+BWx7a50Bhlg==}
+ dependencies:
+ '@algolia/client-common': 4.15.0
+ '@algolia/requester-common': 4.15.0
+ '@algolia/transporter': 4.15.0
+ dev: true
+
+ /@algolia/client-search/4.15.0:
+ resolution: {integrity: sha512-dTwZD4u53WdmexnMcoO2Qd/+YCP3ESXKOtD2MryQ1a9dHwB2Y3Qob0kyS1PG82idwM3enbznvscI9Sf4o9PUWQ==}
+ dependencies:
+ '@algolia/client-common': 4.15.0
+ '@algolia/requester-common': 4.15.0
+ '@algolia/transporter': 4.15.0
+ dev: true
+
+ /@algolia/logger-common/4.15.0:
+ resolution: {integrity: sha512-D8OFwn/HpvQz66goIcjxOKsYBMuxiruxJ3cA/bnc0EiDvSA2P2z6bNQWgS5gbstuTZIJmbhr+53NyOxFkmMNAA==}
+ dev: true
+
+ /@algolia/logger-console/4.15.0:
+ resolution: {integrity: sha512-pQOvVaRSEJQJRXKTnxEA6nN1hipSQadJJ4einw0nIlfMOGZh/kps1ybh8vRUlUGyfEuN/3dyFs0W3Ac7hIItlg==}
+ dependencies:
+ '@algolia/logger-common': 4.15.0
+ dev: true
+
+ /@algolia/requester-browser-xhr/4.15.0:
+ resolution: {integrity: sha512-va186EfALF+6msYZXaoBSxcnFCg3SoWJ+uv1yMyhQRJRe7cZSHWSVT3s40vmar90gxlBu80KMVwVlsvJhJv6ew==}
+ dependencies:
+ '@algolia/requester-common': 4.15.0
+ dev: true
+
+ /@algolia/requester-common/4.15.0:
+ resolution: {integrity: sha512-w0UUzxElbo4hrKg4QP/jiXDNbIJuAthxdlkos9nS8KAPK2XI3R9BlUjLz/ZVs4F9TDGI0mhjrNHhZ12KXcoyhg==}
+ dev: true
+
+ /@algolia/requester-node-http/4.15.0:
+ resolution: {integrity: sha512-eeEOhFtgwKcgAlKAZpgBRZJ0ILSEBCXxZ9uwfVWPD24W1b6z08gVoTJ6J7lCeCnJmudg+tMElDnGzHkjup9CJA==}
+ dependencies:
+ '@algolia/requester-common': 4.15.0
+ dev: true
+
+ /@algolia/transporter/4.15.0:
+ resolution: {integrity: sha512-JoWR+ixG3EmA0UPntQFN/FV5TasYcYu93d5+oKzHFeZ6Z7rtW5Im9iy/Oh/ggk1AAN5fTdqKewtbBpdaYDbKsQ==}
+ dependencies:
+ '@algolia/cache-common': 4.15.0
+ '@algolia/logger-common': 4.15.0
+ '@algolia/requester-common': 4.15.0
+ dev: true
+
/@ampproject/remapping/2.2.0:
resolution: {integrity: sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==}
engines: {node: '>=6.0.0'}
@@ -525,6 +647,44 @@ packages:
mime: 3.0.0
dev: true
+ /@docsearch/css/3.3.3:
+ resolution: {integrity: sha512-6SCwI7P8ao+se1TUsdZ7B4XzL+gqeQZnBc+2EONZlcVa0dVrk0NjETxozFKgMv0eEGH8QzP1fkN+A1rH61l4eg==}
+ dev: true
+
+ /@docsearch/js/3.3.3:
+ resolution: {integrity: sha512-2xAv2GFuHzzmG0SSZgf8wHX0qZX8n9Y1ZirKUk5Wrdc+vH9CL837x2hZIUdwcPZI9caBA+/CzxsS68O4waYjUQ==}
+ dependencies:
+ '@docsearch/react': 3.3.3
+ preact: 10.13.1
+ transitivePeerDependencies:
+ - '@algolia/client-search'
+ - '@types/react'
+ - react
+ - react-dom
+ dev: true
+
+ /@docsearch/react/3.3.3:
+ resolution: {integrity: sha512-pLa0cxnl+G0FuIDuYlW+EBK6Rw2jwLw9B1RHIeS4N4s2VhsfJ/wzeCi3CWcs5yVfxLd5ZK50t//TMA5e79YT7Q==}
+ peerDependencies:
+ '@types/react': '>= 16.8.0 < 19.0.0'
+ react: '>= 16.8.0 < 19.0.0'
+ react-dom: '>= 16.8.0 < 19.0.0'
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ react:
+ optional: true
+ react-dom:
+ optional: true
+ dependencies:
+ '@algolia/autocomplete-core': 1.7.4
+ '@algolia/autocomplete-preset-algolia': 1.7.4_algoliasearch@4.15.0
+ '@docsearch/css': 3.3.3
+ algoliasearch: 4.15.0
+ transitivePeerDependencies:
+ - '@algolia/client-search'
+ dev: true
+
/@emmetio/abbreviation/2.2.3:
resolution: {integrity: sha512-87pltuCPt99aL+y9xS6GPZ+Wmmyhll2WXH73gG/xpGcQ84DRnptBsI2r0BeIQ0EB/SQTOe2ANPqFqj3Rj5FOGA==}
dependencies:
@@ -1516,6 +1676,16 @@ packages:
'@babel/types': 7.21.3
dev: true
+ /@types/chai-subset/1.3.3:
+ resolution: {integrity: sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==}
+ dependencies:
+ '@types/chai': 4.3.4
+ dev: true
+
+ /@types/chai/4.3.4:
+ resolution: {integrity: sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw==}
+ dev: true
+
/@types/debug/4.1.7:
resolution: {integrity: sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==}
dependencies:
@@ -1602,6 +1772,10 @@ packages:
resolution: {integrity: sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==}
dev: true
+ /@types/web-bluetooth/0.0.16:
+ resolution: {integrity: sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==}
+ dev: true
+
/@types/yargs-parser/21.0.0:
resolution: {integrity: sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==}
dev: true
@@ -1850,6 +2024,48 @@ packages:
vue: 3.2.47
dev: true
+ /@vitejs/plugin-vue/4.1.0_vite@4.2.0+vue@3.2.47:
+ resolution: {integrity: sha512-++9JOAFdcXI3lyer9UKUV4rfoQ3T1RN8yDqoCLar86s0xQct5yblxAE+yWgRnU5/0FOlVCpTZpYSBV/bGWrSrQ==}
+ engines: {node: ^14.18.0 || >=16.0.0}
+ peerDependencies:
+ vite: ^4.0.0
+ vue: ^3.2.25
+ dependencies:
+ vite: 4.2.0
+ vue: 3.2.47
+ dev: true
+
+ /@vitest/expect/0.29.3:
+ resolution: {integrity: sha512-z/0JqBqqrdtrT/wzxNrWC76EpkOHdl+SvuNGxWulLaoluygntYyG5wJul5u/rQs5875zfFz/F+JaDf90SkLUIg==}
+ dependencies:
+ '@vitest/spy': 0.29.3
+ '@vitest/utils': 0.29.3
+ chai: 4.3.7
+ dev: true
+
+ /@vitest/runner/0.29.3:
+ resolution: {integrity: sha512-XLi8ctbvOWhUWmuvBUSIBf8POEDH4zCh6bOuVxm/KGfARpgmVF1ku+vVNvyq85va+7qXxtl+MFmzyXQ2xzhAvw==}
+ dependencies:
+ '@vitest/utils': 0.29.3
+ p-limit: 4.0.0
+ pathe: 1.1.0
+ dev: true
+
+ /@vitest/spy/0.29.3:
+ resolution: {integrity: sha512-LLpCb1oOCOZcBm0/Oxbr1DQTuKLRBsSIHyLYof7z4QVE8/v8NcZKdORjMUq645fcfX55+nLXwU/1AQ+c2rND+w==}
+ dependencies:
+ tinyspy: 1.1.1
+ dev: true
+
+ /@vitest/utils/0.29.3:
+ resolution: {integrity: sha512-hg4Ff8AM1GtUnLpUJlNMxrf9f4lZr/xRJjh3uJ0QFP+vjaW82HAxKrmeBmLnhc8Os2eRf+f+VBu4ts7TafPPkA==}
+ dependencies:
+ cli-truncate: 3.1.0
+ diff: 5.1.0
+ loupe: 2.3.6
+ pretty-format: 27.5.1
+ dev: true
+
/@vscode/emmet-helper/2.8.6:
resolution: {integrity: sha512-IIB8jbiKy37zN8bAIHx59YmnIelY78CGHtThnibD/d3tQOKRY83bYVi9blwmZVUZh6l9nfkYH3tvReaiNxY9EQ==}
dependencies:
@@ -1972,6 +2188,31 @@ packages:
resolution: {integrity: sha512-BHGyyGN3Q97EZx0taMQ+OLNuZcW3d37ZEVmEAyeoA9ERdGvm9Irc/0Fua8SNyOtV1w6BS4q25wbMzJujO9HIfQ==}
dev: true
+ /@vueuse/core/9.13.0_vue@3.2.47:
+ resolution: {integrity: sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==}
+ dependencies:
+ '@types/web-bluetooth': 0.0.16
+ '@vueuse/metadata': 9.13.0
+ '@vueuse/shared': 9.13.0_vue@3.2.47
+ vue-demi: 0.13.11_vue@3.2.47
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+ - vue
+ dev: true
+
+ /@vueuse/metadata/9.13.0:
+ resolution: {integrity: sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==}
+ dev: true
+
+ /@vueuse/shared/9.13.0_vue@3.2.47:
+ resolution: {integrity: sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==}
+ dependencies:
+ vue-demi: 0.13.11_vue@3.2.47
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+ - vue
+ dev: true
+
/@webassemblyjs/ast/1.11.1:
resolution: {integrity: sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==}
dependencies:
@@ -2106,6 +2347,11 @@ packages:
acorn: 8.8.2
dev: true
+ /acorn-walk/8.2.0:
+ resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==}
+ engines: {node: '>=0.4.0'}
+ dev: true
+
/acorn/8.8.2:
resolution: {integrity: sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==}
engines: {node: '>=0.4.0'}
@@ -2137,6 +2383,25 @@ packages:
uri-js: 4.4.1
dev: true
+ /algoliasearch/4.15.0:
+ resolution: {integrity: sha512-+vgKQF5944dYsz9zhKk07JbOYeNdKisoD5GeG0woBL3nLzbn2a+nGwki60DXg7CXvaFXBcTXyJG4C+VaBVd44g==}
+ dependencies:
+ '@algolia/cache-browser-local-storage': 4.15.0
+ '@algolia/cache-common': 4.15.0
+ '@algolia/cache-in-memory': 4.15.0
+ '@algolia/client-account': 4.15.0
+ '@algolia/client-analytics': 4.15.0
+ '@algolia/client-common': 4.15.0
+ '@algolia/client-personalization': 4.15.0
+ '@algolia/client-search': 4.15.0
+ '@algolia/logger-common': 4.15.0
+ '@algolia/logger-console': 4.15.0
+ '@algolia/requester-browser-xhr': 4.15.0
+ '@algolia/requester-common': 4.15.0
+ '@algolia/requester-node-http': 4.15.0
+ '@algolia/transporter': 4.15.0
+ dev: true
+
/ansi-align/3.0.1:
resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==}
dependencies:
@@ -2167,6 +2432,10 @@ packages:
engines: {node: '>=12'}
dev: true
+ /ansi-sequence-parser/1.1.0:
+ resolution: {integrity: sha512-lEm8mt52to2fT8GhciPCGeCXACSz2UwIN4X2e2LJSnZ5uAbn2/dsYdOmUXq0AtWS5cpAupysIneExOgH0Vd2TQ==}
+ dev: true
+
/ansi-styles/3.2.1:
resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==}
engines: {node: '>=4'}
@@ -2181,6 +2450,11 @@ packages:
color-convert: 2.0.1
dev: true
+ /ansi-styles/5.2.0:
+ resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==}
+ engines: {node: '>=10'}
+ dev: true
+
/ansi-styles/6.2.1:
resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==}
engines: {node: '>=12'}
@@ -2307,6 +2581,10 @@ packages:
es-shim-unscopables: 1.0.0
dev: true
+ /assertion-error/1.1.0:
+ resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==}
+ dev: true
+
/astro/2.1.3:
resolution: {integrity: sha512-5LFo/ixDXs84tgrSbzz0X5c7nzLfkag7w4tgOpBRL/DkveP83v+nSe3KjqwYLPL5vNY9UvryKHsfC0uu4TQz0g==}
engines: {node: '>=16.12.0', npm: '>=6.14.0'}
@@ -2448,6 +2726,10 @@ packages:
readable-stream: 3.6.2
dev: true
+ /body-scroll-lock/4.0.0-beta.0:
+ resolution: {integrity: sha512-a7tP5+0Mw3YlUJcGAKUqIBkYYGlYxk2fnCasq/FUph1hadxlTRjF+gAcZksxANnaMnALjxEddmSi/H3OR8ugcQ==}
+ dev: true
+
/boolbase/1.0.0:
resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==}
dev: true
@@ -2600,6 +2882,19 @@ packages:
resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==}
dev: true
+ /chai/4.3.7:
+ resolution: {integrity: sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==}
+ engines: {node: '>=4'}
+ dependencies:
+ assertion-error: 1.1.0
+ check-error: 1.0.2
+ deep-eql: 4.1.3
+ get-func-name: 2.0.0
+ loupe: 2.3.6
+ pathval: 1.1.1
+ type-detect: 4.0.8
+ dev: true
+
/chalk/2.4.2:
resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==}
engines: {node: '>=4'}
@@ -2650,6 +2945,10 @@ packages:
resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==}
dev: true
+ /check-error/1.0.2:
+ resolution: {integrity: sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==}
+ dev: true
+
/chokidar/3.5.3:
resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==}
engines: {node: '>= 8.10.0'}
@@ -2707,6 +3006,14 @@ packages:
engines: {node: '>=6'}
dev: true
+ /cli-truncate/3.1.0:
+ resolution: {integrity: sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ dependencies:
+ slice-ansi: 5.0.0
+ string-width: 5.1.2
+ dev: true
+
/cli-width/4.0.0:
resolution: {integrity: sha512-ZksGS2xpa/bYkNzN3BAw1wEjsLV/ZKOf/CCrJ/QOBsxx6fOARIkwTutxp1XIOIohi6HKmOFjMoK/XaqDVUpEEw==}
engines: {node: '>= 12'}
@@ -3028,6 +3335,13 @@ packages:
character-entities: 2.0.2
dev: true
+ /deep-eql/4.1.3:
+ resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==}
+ engines: {node: '>=6'}
+ dependencies:
+ type-detect: 4.0.8
+ dev: true
+
/deep-is/0.1.4:
resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
dev: true
@@ -4128,6 +4442,10 @@ packages:
engines: {node: 6.* || 8.* || >= 10.*}
dev: true
+ /get-func-name/2.0.0:
+ resolution: {integrity: sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==}
+ dev: true
+
/get-intrinsic/1.2.0:
resolution: {integrity: sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==}
dependencies:
@@ -4776,6 +5094,11 @@ packages:
engines: {node: '>=8'}
dev: true
+ /is-fullwidth-code-point/4.0.0:
+ resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==}
+ engines: {node: '>=12'}
+ dev: true
+
/is-glob/4.0.3:
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
engines: {node: '>=0.10.0'}
@@ -5208,6 +5531,12 @@ packages:
resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==}
dev: true
+ /loupe/2.3.6:
+ resolution: {integrity: sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==}
+ dependencies:
+ get-func-name: 2.0.0
+ dev: true
+
/lru-cache/5.1.1:
resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
dependencies:
@@ -6242,6 +6571,13 @@ packages:
yocto-queue: 0.1.0
dev: true
+ /p-limit/4.0.0:
+ resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ dependencies:
+ yocto-queue: 1.0.0
+ dev: true
+
/p-locate/4.1.0:
resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==}
engines: {node: '>=8'}
@@ -6363,6 +6699,10 @@ packages:
resolution: {integrity: sha512-ODbEPR0KKHqECXW1GoxdDb+AZvULmXjVPy4rt+pGo2+TnjJTIPJQSVS6N63n8T2Ip+syHhbn52OewKicV0373w==}
dev: true
+ /pathval/1.1.1:
+ resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==}
+ dev: true
+
/perfect-debounce/0.1.3:
resolution: {integrity: sha512-NOT9AcKiDGpnV/HBhI22Str++XWcErO/bALvHCuhv33owZW/CjH8KAFLZDCmu3727sihe0wTxpDhyGc6M8qacQ==}
dev: true
@@ -6760,6 +7100,10 @@ packages:
source-map-js: 1.0.2
dev: true
+ /preact/10.13.1:
+ resolution: {integrity: sha512-KyoXVDU5OqTpG9LXlB3+y639JAGzl8JSBXLn1J9HTSB3gbKcuInga7bZnXLlxmK94ntTs1EFeZp0lrja2AuBYQ==}
+ dev: true
+
/preferred-pm/3.0.3:
resolution: {integrity: sha512-+wZgbxNES/KlJs9q40F/1sfOd/j7f1O9JaHcW5Dsn3aUUOZg3L2bjpVUcKV2jvtElYfoTuQiNeMfQJ4kwUAhCQ==}
engines: {node: '>=10'}
@@ -6796,6 +7140,15 @@ packages:
engines: {node: ^14.13.1 || >=16.0.0}
dev: true
+ /pretty-format/27.5.1:
+ resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==}
+ engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
+ dependencies:
+ ansi-regex: 5.0.1
+ ansi-styles: 5.2.0
+ react-is: 17.0.2
+ dev: true
+
/prismjs/1.29.0:
resolution: {integrity: sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==}
engines: {node: '>=6'}
@@ -6862,6 +7215,10 @@ packages:
flat: 5.0.2
dev: true
+ /react-is/17.0.2:
+ resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==}
+ dev: true
+
/read-cache/1.0.0:
resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==}
dependencies:
@@ -7309,6 +7666,15 @@ packages:
vscode-textmate: 6.0.0
dev: true
+ /shiki/0.14.1:
+ resolution: {integrity: sha512-+Jz4nBkCBe0mEDqo1eKRcCdjRtrCjozmcbTUjbPTX7OOJfEbTZzlUWlZtGe3Gb5oV1/jnojhG//YZc3rs9zSEw==}
+ dependencies:
+ ansi-sequence-parser: 1.1.0
+ jsonc-parser: 3.2.0
+ vscode-oniguruma: 1.7.0
+ vscode-textmate: 8.0.0
+ dev: true
+
/side-channel/1.0.4:
resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==}
dependencies:
@@ -7317,6 +7683,10 @@ packages:
object-inspect: 1.12.3
dev: true
+ /siginfo/2.0.0:
+ resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==}
+ dev: true
+
/signal-exit/3.0.7:
resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
dev: true
@@ -7335,6 +7705,14 @@ packages:
engines: {node: '>=12'}
dev: true
+ /slice-ansi/5.0.0:
+ resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==}
+ engines: {node: '>=12'}
+ dependencies:
+ ansi-styles: 6.2.1
+ is-fullwidth-code-point: 4.0.0
+ dev: true
+
/smob/0.0.6:
resolution: {integrity: sha512-V21+XeNni+tTyiST1MHsa84AQhT1aFZipzPpOFAVB8DkHzwJyjjAmt9bgwnuZiZWnIbMo2duE29wybxv/7HWUw==}
dev: true
@@ -7408,6 +7786,10 @@ packages:
deprecated: 'Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility'
dev: true
+ /stackback/0.0.2:
+ resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==}
+ dev: true
+
/standard-as-callback/2.1.0:
resolution: {integrity: sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==}
dev: true
@@ -7727,6 +8109,20 @@ packages:
resolution: {integrity: sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==}
dev: true
+ /tinybench/2.4.0:
+ resolution: {integrity: sha512-iyziEiyFxX4kyxSp+MtY1oCH/lvjH3PxFN8PGCDeqcZWAJ/i+9y+nL85w99PxVzrIvew/GSkSbDYtiGVa85Afg==}
+ dev: true
+
+ /tinypool/0.3.1:
+ resolution: {integrity: sha512-zLA1ZXlstbU2rlpA4CIeVaqvWq41MTWqLY3FfsAXgC8+f7Pk7zroaJQxDgxn1xNudKW6Kmj4808rPFShUlIRmQ==}
+ engines: {node: '>=14.0.0'}
+ dev: true
+
+ /tinyspy/1.1.1:
+ resolution: {integrity: sha512-UVq5AXt/gQlti7oxoIg5oi/9r0WpF7DGEVwXgqWSMmyN16+e3tl5lIvTaOpJ3TAtu5xFzWccFRM4R5NaWHF+4g==}
+ engines: {node: '>=14.0.0'}
+ dev: true
+
/tmp/0.0.33:
resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==}
engines: {node: '>=0.6.0'}
@@ -7869,6 +8265,11 @@ packages:
prelude-ls: 1.2.1
dev: true
+ /type-detect/4.0.8:
+ resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==}
+ engines: {node: '>=4'}
+ dev: true
+
/type-fest/0.13.1:
resolution: {integrity: sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==}
engines: {node: '>=10'}
@@ -8232,6 +8633,27 @@ packages:
- terser
dev: true
+ /vite-node/0.29.3_@types+node@18.15.3:
+ resolution: {integrity: sha512-QYzYSA4Yt2IiduEjYbccfZQfxKp+T1Do8/HEpSX/G5WIECTFKJADwLs9c94aQH4o0A+UtCKU61lj1m5KvbxxQA==}
+ engines: {node: '>=v14.16.0'}
+ hasBin: true
+ dependencies:
+ cac: 6.7.14
+ debug: 4.3.4
+ mlly: 1.2.0
+ pathe: 1.1.0
+ picocolors: 1.0.0
+ vite: 4.2.0_@types+node@18.15.3
+ transitivePeerDependencies:
+ - '@types/node'
+ - less
+ - sass
+ - stylus
+ - sugarss
+ - supports-color
+ - terser
+ dev: true
+
/vite-plugin-checker/0.5.6_vite@4.1.4:
resolution: {integrity: sha512-ftRyON0gORUHDxcDt2BErmsikKSkfvl1i2DoP6Jt2zDO9InfvM6tqO1RkXhSjkaXEhKPea6YOnhFaZxW3BzudQ==}
engines: {node: '>=14.16'}
@@ -8393,6 +8815,88 @@ packages:
vite: 4.2.0
dev: true
+ /vitepress/1.0.0-alpha.60:
+ resolution: {integrity: sha512-GI5iLDkZRqGEPixbSloT+p6pbKcMh9ykRRxt8vf9AjV1gaPit6Stg/t9WNxTdIhKVCuQMexGs1605DNApSRK2A==}
+ hasBin: true
+ dependencies:
+ '@docsearch/css': 3.3.3
+ '@docsearch/js': 3.3.3
+ '@vitejs/plugin-vue': 4.1.0_vite@4.2.0+vue@3.2.47
+ '@vue/devtools-api': 6.5.0
+ '@vueuse/core': 9.13.0_vue@3.2.47
+ body-scroll-lock: 4.0.0-beta.0
+ shiki: 0.14.1
+ vite: 4.2.0
+ vue: 3.2.47
+ transitivePeerDependencies:
+ - '@algolia/client-search'
+ - '@types/node'
+ - '@types/react'
+ - '@vue/composition-api'
+ - less
+ - react
+ - react-dom
+ - sass
+ - stylus
+ - sugarss
+ - terser
+ dev: true
+
+ /vitest/0.29.3:
+ resolution: {integrity: sha512-muMsbXnZsrzDGiyqf/09BKQsGeUxxlyLeLK/sFFM4EXdURPQRv8y7dco32DXaRORYP0bvyN19C835dT23mL0ow==}
+ engines: {node: '>=v14.16.0'}
+ hasBin: true
+ peerDependencies:
+ '@edge-runtime/vm': '*'
+ '@vitest/browser': '*'
+ '@vitest/ui': '*'
+ happy-dom: '*'
+ jsdom: '*'
+ peerDependenciesMeta:
+ '@edge-runtime/vm':
+ optional: true
+ '@vitest/browser':
+ optional: true
+ '@vitest/ui':
+ optional: true
+ happy-dom:
+ optional: true
+ jsdom:
+ optional: true
+ dependencies:
+ '@types/chai': 4.3.4
+ '@types/chai-subset': 1.3.3
+ '@types/node': 18.15.3
+ '@vitest/expect': 0.29.3
+ '@vitest/runner': 0.29.3
+ '@vitest/spy': 0.29.3
+ '@vitest/utils': 0.29.3
+ acorn: 8.8.2
+ acorn-walk: 8.2.0
+ cac: 6.7.14
+ chai: 4.3.7
+ debug: 4.3.4
+ local-pkg: 0.4.3
+ pathe: 1.1.0
+ picocolors: 1.0.0
+ source-map: 0.6.1
+ std-env: 3.3.2
+ strip-literal: 1.0.1
+ tinybench: 2.4.0
+ tinypool: 0.3.1
+ tinyspy: 1.1.1
+ vite: 4.2.0_@types+node@18.15.3
+ vite-node: 0.29.3_@types+node@18.15.3
+ why-is-node-running: 2.2.2
+ transitivePeerDependencies:
+ - less
+ - sass
+ - stylus
+ - sugarss
+ - supports-color
+ - terser
+ dev: true
+
/vscode-css-languageservice/6.2.4:
resolution: {integrity: sha512-9UG0s3Ss8rbaaPZL1AkGzdjrGY8F+P+Ne9snsrvD9gxltDGhsn8C2dQpqQewHrMW37OvlqJoI8sUU2AWDb+qNw==}
dependencies:
@@ -8478,6 +8982,10 @@ packages:
resolution: {integrity: sha512-gu73tuZfJgu+mvCSy4UZwd2JXykjK9zAZsfmDeut5dx/1a7FeTk0XwJsSuqQn+cuMCGVbIBfl+s53X4T19DnzQ==}
dev: true
+ /vscode-textmate/8.0.0:
+ resolution: {integrity: sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==}
+ dev: true
+
/vscode-uri/2.1.2:
resolution: {integrity: sha512-8TEXQxlldWAuIODdukIb+TR5s+9Ds40eSJrw+1iDDA9IFORPjMELarNQE3myz5XIkWWpdprmJjm1/SxMlWOC8A==}
dev: true
@@ -8492,6 +9000,21 @@ packages:
ufo: 1.1.1
dev: true
+ /vue-demi/0.13.11_vue@3.2.47:
+ resolution: {integrity: sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==}
+ engines: {node: '>=12'}
+ hasBin: true
+ requiresBuild: true
+ peerDependencies:
+ '@vue/composition-api': ^1.0.0-rc.1
+ vue: ^3.0.0-0 || ^2.6.0
+ peerDependenciesMeta:
+ '@vue/composition-api':
+ optional: true
+ dependencies:
+ vue: 3.2.47
+ dev: true
+
/vue-devtools-stub/0.1.0:
resolution: {integrity: sha512-RutnB7X8c5hjq39NceArgXg28WZtZpGc3+J16ljMiYnFhKvd8hITxSWQSQ5bvldxMDU6gG5mkxl1MTQLXckVSQ==}
dev: true
@@ -8651,6 +9174,15 @@ packages:
isexe: 2.0.0
dev: true
+ /why-is-node-running/2.2.2:
+ resolution: {integrity: sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==}
+ engines: {node: '>=8'}
+ hasBin: true
+ dependencies:
+ siginfo: 2.0.0
+ stackback: 0.0.2
+ dev: true
+
/wide-align/1.1.5:
resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==}
dependencies:
@@ -8752,6 +9284,11 @@ packages:
engines: {node: '>=10'}
dev: true
+ /yocto-queue/1.0.0:
+ resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==}
+ engines: {node: '>=12.20'}
+ dev: true
+
/zhead/2.0.4:
resolution: {integrity: sha512-V4R94t3ifk9AURym6OskbKcnowzgp5Z88tkoL/NF67vyryNxC62u6mx5F1Ux4oh4+YN7FFmKYEyWy6m5kfPH6g==}
dev: true
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
index fe455ac..d1cce72 100644
--- a/pnpm-workspace.yaml
+++ b/pnpm-workspace.yaml
@@ -1,2 +1,3 @@
packages:
+ - docs
- examples/*
diff --git a/scripts/postbuild.ts b/scripts/postbuild.ts
index d495f2e..5481f07 100644
--- a/scripts/postbuild.ts
+++ b/scripts/postbuild.ts
@@ -1,6 +1,6 @@
-import { basename, dirname, resolve } from 'path'
-import { promises as fs } from 'fs'
-import { fileURLToPath } from 'url'
+import { basename, dirname, resolve } from 'node:path'
+import { promises as fs } from 'node:fs'
+import { fileURLToPath } from 'node:url'
import fg from 'fast-glob'
import chalk from 'chalk'
diff --git a/src/astro.ts b/src/astro.ts
index ca3a05d..cbeb2e6 100644
--- a/src/astro.ts
+++ b/src/astro.ts
@@ -7,9 +7,8 @@ export default function (options: Options) {
name: 'unplugin-fonts',
hooks: {
'astro:config:setup': async (astro: any) => {
- if (options?.custom) {
+ if (options?.custom)
options.custom.stripPrefix = 'public/'
- }
astro.config.vite.plugins ||= []
astro.config.vite.plugins.push(unplugin.vite(options))
@@ -17,7 +16,6 @@ export default function (options: Options) {
// const links = getHeadLinkTags(options, astro.config.root.toString())
// const linksString: string[] = []
-
// for (const link of links) {
// linksString.push(` `${key}="${value}"`).join(' ')} />`)
// }
diff --git a/src/head.ts b/src/head.ts
index 5bace70..2d9385e 100644
--- a/src/head.ts
+++ b/src/head.ts
@@ -1,4 +1,4 @@
import type { HtmlTagDescriptor } from 'vite'
// exposed via virtual module
-export const links: HtmlTagDescriptor[] = []
\ No newline at end of file
+export const links: HtmlTagDescriptor[] = []
diff --git a/src/index.ts b/src/index.ts
index f7b6826..1e64477 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -5,10 +5,10 @@ import { fontsourceVirtualModule } from './loaders/fontsource'
import { customVirtualModule } from './loaders/custom'
const virtualStylesId = 'unfonts.css'
-const resolvedVirtualStylesId = '\0' + virtualStylesId
+const resolvedVirtualStylesId = `\0${virtualStylesId}`
const virtualModuleId = 'unplugin-fonts/head'
-const resolvedVirtualModuleId = '\0' + virtualModuleId
+const resolvedVirtualModuleId = `\0${virtualModuleId}`
export default createUnplugin((userOptions) => {
const options = userOptions || {}
@@ -18,30 +18,25 @@ export default createUnplugin((userOptions) => {
name: 'unplugin-fonts',
enforce: 'pre',
resolveId(id) {
- if (id === virtualStylesId) {
+ if (id === virtualStylesId)
return resolvedVirtualStylesId
- }
-
- if (id === virtualModuleId) {
+
+ if (id === virtualModuleId)
return resolvedVirtualModuleId
- }
},
load(id) {
- if (id === resolvedVirtualModuleId) {
+ if (id === resolvedVirtualModuleId)
return `export const links = ${JSON.stringify(getHeadLinkTags(options, root))}`
- }
-
+
if (id === resolvedVirtualStylesId) {
const source: string[] = []
- if (options.fontsource) {
+ if (options.fontsource)
source.push(fontsourceVirtualModule(options.fontsource))
- }
- if (options.custom) {
+ if (options.custom)
source.push(customVirtualModule(options.custom, root))
- }
return source.join('\n')
}
diff --git a/src/loaders/custom.ts b/src/loaders/custom.ts
index e8f55c7..27ca59e 100644
--- a/src/loaders/custom.ts
+++ b/src/loaders/custom.ts
@@ -1,292 +1,238 @@
import type { HtmlTagDescriptor } from 'vite'
import { sync as glob } from 'fast-glob'
-import { resolve, join, relative } from 'pathe'
-
-interface CustomFontFace {
- src: string[]
- name: string
- weight: number | string
- style: string
- display: 'auto' | 'block' | 'swap' | 'fallback' | 'optional'
- local?: string | string[]
+import { basename as _basename, extname, join, relative } from 'pathe'
+import type { CustomFontFace, CustomFontFamily, CustomFonts } from '../types'
+
+type ResolvedCustomFonts = Required> & { families: CustomFontFamily[] }
+
+function resolveUserOption(options: CustomFonts): ResolvedCustomFonts {
+ let {
+ families = [],
+ preload = true,
+ prefetch = false,
+ injectTo = 'head-prepend',
+ display = 'auto',
+ stripPrefix = 'public/',
+ } = options
+
+ // --- Cast as array of `CustomFontFamily`.
+ if (!Array.isArray(families)) {
+ families = Object.entries(families)
+ .map(([name, family]) => (Array.isArray(family) || typeof family === 'string')
+ ? { name, src: family }
+ : { name, ...family },
+ )
+ }
+
+ return {
+ families,
+ preload,
+ prefetch,
+ injectTo,
+ display,
+ stripPrefix,
+ }
+}
+
+export function customVirtualModule(userOptions: CustomFonts, root: string) {
+ const options = resolveUserOption(userOptions)
+
+ const css: string[] = []
+
+ for (const family of options.families) {
+ const faces = resolveFontFiles(family, options, root)
+
+ // --- Generate CSS `@font-face` rules.
+ for (const face of faces)
+ css.push(generateFontCSS(face))
+ }
+
+ return css.join('\n')
}
-export interface CustomFontFamily {
- /**
- * Name of the font family.
- * @example 'Comic Sans MS'
- */
- name: string
- /**
- * Regex(es) of font files to import. The names of the files will
- * predicate the `font-style` and `font-weight` values of the `@font-rule`'s.
- * @see https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight#common_weight_name_mapping
- *
- * @example
- * A value of `./RobotoBoldItalic.*` will create this `@font-rule`:
- *
- * ```css
- * font-face {
- * font-family: 'Roboto';
- * src: url(./RobotoBoldItalic.ttf) format('truetype')
- * url(./RobotoBoldItalic.woff) format('woff')
- * url(./RobotoBoldItalic.woff2) format('woff2');
- * font-weight: bold;
- * font-style: italic;
- * font-display: auto;
- * }
- * ```
- */
- src: string | string[]
- /**
- * Local name of the font. Used to add `src: local()` to `@font-rule`.
- * @see https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face#description
- */
- local?: string | string[]
+export function customLoader(userOptions: CustomFonts, root: string) {
+ const options = resolveUserOption(userOptions)
+
+ const tags: HtmlTagDescriptor[] = []
+
+ // --- Iterate over font families and their faces.
+ for (const family of options.families) {
+ const faces = resolveFontFiles(family, options, root)
+
+ // --- We can not do a prefetch and a preload for the same files.
+ if (options.preload && options.prefetch) {
+ console.warn('unplugin-fonts: Prefetch and a Preload options can not be used together.')
+ console.warn('unplugin-fonts: The prefetch stand for a lower priority for the resource (maybe we will need it in a future page) whereas preload is for the current page, so we can not have both.')
+ }
+ if (options.preload || options.prefetch) {
+ // --- Generate `` tags.
+ for (const face of faces)
+ tags.push(...createFontLinks(options, face))
+ }
+ }
+
+ return tags
}
-export interface CustomFonts {
- /**
- * Font families.
- */
- families: CustomFontFamily[] | Record>
- /**
- * Defines the default `font-display` value used for the generated
- * `@font-rule` classes.
- * @see https://developer.mozilla.org/fr/docs/Web/CSS/@font-face/font-display
- * @default 'auto'
- */
- display?: 'auto' | 'block' | 'swap' | 'fallback' | 'optional'
- /**
- * Using `` will trigger a request for the WebFont
- * early in the critical rendering path, without having to wait for the
- * CSSOM to be created.
- * @see https://web.dev/optimize-webfont-loading/#preload-your-webfont-resources
- * @default true
- */
- preload?: boolean
-
- /**
- * Using `` is intended for prefetching resources
- * that will be used in the next navigation/page load
- * (e.g. when you go to the next page)
- *
- * Note: this can not be used with `preload`
- * @default false
- */
- prefetch?: boolean
- /**
- * @default: 'head-prepend'
- */
- injectTo?: 'head' | 'body' | 'head-prepend' | 'body-prepend'
-
- /**
- * Remove the prefix from the front path
- * @default: 'public/'
- */
- stripPrefix?: string
+function resolveFontFiles(family: CustomFontFamily, options: ResolvedCustomFonts, root: string) {
+ const sources = Array.isArray(family.src) ? family.src : [family.src]
+ const facesMap: Record = {}
+
+ for (const source of sources) {
+ const results = glob(join(root, source), { absolute: true, cwd: root, onlyFiles: true })
+
+ for (const file of results) {
+ const ext = extname(file)
+ const basename = _basename(file, ext)
+
+ let format = ''
+ switch (ext) {
+ case '.woff':
+ format = 'woff'
+ break
+ case '.woff2':
+ format = 'woff2'
+ break
+ case '.ttf':
+ format = 'truetype'
+ break
+ case '.otf':
+ format = 'opentype'
+ break
+ case '.svg':
+ format = 'svg'
+ break
+ default:
+ format = ext.replace('.', '')
+ }
+
+ facesMap[basename] ||= {
+ source,
+ name: family.name,
+ basename,
+ weight: extractWeight(basename),
+ style: extractStyle(basename),
+ local: family.local,
+ display: options.display,
+ files: [],
+ }
+ facesMap[basename].files.push({
+ src: file,
+ path: join('/', relative(root, file.replace(options.stripPrefix, ''))),
+ format,
+ ext,
+ })
+ }
+ }
+
+ const faces: CustomFontFace[] = []
+ for (const face of Object.values(facesMap)) {
+ if (!family.transform) {
+ faces.push(face)
+ continue
+ }
+
+ const transformed = family.transform(face)
+ if (transformed)
+ faces.push(transformed)
+ }
+
+ return faces
}
-const resolveWeight = (weightOrSrc?: string | number) => {
- if (typeof weightOrSrc === 'number')
- return weightOrSrc
- if (!weightOrSrc)
+function extractWeight(filename?: string) {
+ if (!filename)
return 400
- weightOrSrc = weightOrSrc.toLowerCase()
- if (weightOrSrc.includes('thin'))
+
+ filename = filename.toLowerCase()
+
+ if (filename.includes('thin'))
return 100
- if (weightOrSrc.includes('extralight'))
+ if (filename.includes('extralight'))
return 200
- if (weightOrSrc.includes('ultralight'))
+ if (filename.includes('ultralight'))
return 200
- if (weightOrSrc.includes('light'))
+ if (filename.includes('light'))
return 300
- if (weightOrSrc.includes('normal'))
+ if (filename.includes('normal'))
return 400
- if (weightOrSrc.includes('medium'))
+ if (filename.includes('medium'))
return 500
- if (weightOrSrc.includes('semibold'))
+ if (filename.includes('semibold'))
return 600
- if (weightOrSrc.includes('demibold'))
+ if (filename.includes('demibold'))
return 600
- if (weightOrSrc.includes('extrabold'))
+ if (filename.includes('extrabold'))
return 800
- if (weightOrSrc.includes('ultrabold'))
+ if (filename.includes('ultrabold'))
return 800
- if (weightOrSrc.includes('bold'))
+ if (filename.includes('bold'))
return 700
- if (weightOrSrc.includes('black'))
+ if (filename.includes('black'))
return 900
- if (weightOrSrc.includes('heavy'))
+ if (filename.includes('heavy'))
return 900
return 400
}
-const resolveStyle = (styleOrSrc?: string) => {
- if (!styleOrSrc)
+function extractStyle(filename?: string) {
+ if (!filename)
return 'normal'
- styleOrSrc = styleOrSrc.toLowerCase()
- if (styleOrSrc.includes('normal'))
+
+ filename = filename.toLowerCase()
+ if (filename.includes('normal'))
return 'normal'
- if (styleOrSrc.includes('italic'))
+
+ if (filename.includes('italic'))
return 'italic'
- if (styleOrSrc.includes('oblique'))
+
+ if (filename.includes('oblique'))
return 'oblique'
+
return 'normal'
}
-const createFontFaceCSS = ({ name, src, local, weight, style, display }: CustomFontFace) => {
+function generateFontCSS(face: CustomFontFace) {
// --- Format sources.
- const srcs = (Array.isArray(src) ? src : [src])
- .filter(Boolean)
- .map((url) => {
- let format = url.split('.').pop()
- if (format === 'ttf')
- format = 'truetype'
- if (format === 'otf')
- format = 'opentype'
- return `url('${join('/', url)}') format('${format}')`
+ const srcs = face.files
+ .map((file) => {
+ return `url('${file.path}') format('${file.format}')`
})
.join(',\n\t\t')
// --- Format local.
- const locals = (Array.isArray(local) ? local : [local])
+ const locals = (Array.isArray(face.local) ? face.local : [face.local])
.filter(Boolean)
.map(x => `local('${x}')`)
.join(', ')
// --- Return CSS rule as string.
- return `@font-face {
- font-family: '${name}';
- src: ${[srcs, locals].filter(Boolean).join(',')};
- font-weight: ${weight};
- font-style: ${style};
- font-display: ${display};
-}`
-}
-
-const createFontFaceLink = (
- prefetch = false,
- injectTo: 'head' | 'body' | 'head-prepend' | 'body-prepend' = 'head-prepend',
-) => (href: string) => {
- return {
- tag: 'link',
- injectTo,
- attrs: {
- rel: prefetch ? 'prefetch' : 'preload',
- as: 'font',
- type: `font/${href.split('.').pop()}`,
- href,
- crossorigin: true,
- },
- }
-}
-
-function resolveFontfaceFiles({ src, root }: {
- src: string | string[]
- root: string
-}) {
- const facesGrouped: Record = {};
-
- (Array.isArray(src) ? src : [src])
- .flatMap(x => {
- return glob(join(root, x), { absolute: true, cwd: root, onlyFiles: true })
- })
- .filter(Boolean)
- .forEach((src) => {
- const srcNoExt = src.match(/(.*)\.(\w|\d)+$/)?.[1].toLowerCase()
- if (srcNoExt)
- facesGrouped[srcNoExt] = (facesGrouped[srcNoExt] ?? []).concat(src)
- })
-
- return Object.entries(facesGrouped).map(([srcNoExt, src]) => ({
- srcNoExt, src
- }))
-}
-
-export function customVirtualModule(options: CustomFonts, root: string) {
- const css: string[] = []
-
- /* eslint-disable prefer-const */
- let {
- families = [],
- display = 'auto',
- stripPrefix = 'public/',
- } = options
- /* eslint-enable prefer-const */
-
- // --- Cast as array of `CustomFontFamily`.
- if (!Array.isArray(families)) {
- families = Object.entries(families)
- .map(([name, family]) => (Array.isArray(family) || typeof family === 'string')
- ? { name, src: family }
- : { name, ...family },
- )
- }
-
- for (const { name, src, local } of families) {
- const faces = resolveFontfaceFiles({ src, root })
- .map((item) => ({
- name,
- src: item.src.map(x => join('/', relative(root, x.replace(stripPrefix, '')))),
- weight: resolveWeight(item.srcNoExt),
- style: resolveStyle(item.srcNoExt),
- display,
- local,
- }))
- // --- Generate CSS `@font-face` rules.
- for (const face of faces) css.push(createFontFaceCSS(face))
- }
-
- return css.join('\n\n')
+ return [
+ '@font-face {',
+ ` font-family: '${face.name}';`,
+ ` src: ${[srcs, locals].filter(Boolean).join(',')};`,
+ ` font-weight: ${face.weight};`,
+ ` font-style: ${face.style};`,
+ ` font-display: ${face.display};`,
+ '}',
+ ].join('\n')
}
-export function customLoader(options: CustomFonts, root: string) {
- const tags: HtmlTagDescriptor[] = []
- // const css: string[] = []
-
- // --- Extract and defaults plugin options.
- /* eslint-disable prefer-const */
- let {
- families = [],
- preload = true,
- prefetch = false,
- injectTo = 'head-prepend',
- stripPrefix = 'public/',
- } = options
- /* eslint-enable prefer-const */
-
- // --- Cast as array of `CustomFontFamily`.
- if (!Array.isArray(families)) {
- families = Object.entries(families)
- .map(([name, family]) => (Array.isArray(family) || typeof family === 'string')
- ? { name, src: family }
- : { name, ...family },
- )
- }
-
- // --- Iterate over font families and their faces.
- for (const { src } of families) {
- const faces = resolveFontfaceFiles({ src, root })
-
- const hrefs = faces
- .flatMap(face => face.src)
- .map(src => join('/', relative(root, src.replace(stripPrefix, ''))))
-
- // --- Generate `` tags.
- // --- We can not do a prefetch and a preload for the same files.
- if (preload && prefetch) {
- console.warn('unplugin-fonts: Prefetch and a Preload options can not be used together.')
- console.warn('unplugin-fonts: The prefetch stand for a lower priority for the resource (maybe we will need it in a future page) whereas preload is for the current page, so we can not have both.')
- }
- if (preload || prefetch)
- tags.push(...hrefs.map(createFontFaceLink(prefetch, injectTo)))
-
- // // --- Generate CSS `@font-face` rules.
- // for (const face of faces) css.push(createFontFaceCSS(face))
+function createFontLinks(options: ResolvedCustomFonts, face: CustomFontFace) {
+ const links: HtmlTagDescriptor[] = []
+
+ for (const file of face.files) {
+ links.push({
+ tag: 'link',
+ injectTo: options.injectTo,
+ attrs: {
+ rel: options.prefetch ? 'prefetch' : 'preload',
+ as: 'font',
+ type: `font/${file.ext.replace('.', '')}`,
+ href: file.path,
+ crossorigin: true,
+ },
+ })
}
-
- // --- Return tags and CSS.
- return tags
+ return links
}
-
diff --git a/src/loaders/fontsource.ts b/src/loaders/fontsource.ts
index 30c679a..bd643b1 100644
--- a/src/loaders/fontsource.ts
+++ b/src/loaders/fontsource.ts
@@ -1,16 +1,4 @@
-
-export interface FontsourceFontFamily {
- name: string
- variables?: ('variable' | 'variable-italic' | 'variable-full' | 'variable-full-italic')[]
- weights: (100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900)[]
- styles?: ('italic' | 'normal')[]
- subset?: string
-}
-export interface FontsourceFonts {
- families: (string | FontsourceFontFamily)[]
- // text?: string
- // display?: 'auto' | 'block' | 'swap' | 'fallback' | 'optional'
-}
+import type { FontsourceFonts } from '../types'
export function fontsourceVirtualModule(options?: FontsourceFonts) {
const source: string[] = []
@@ -19,52 +7,53 @@ export function fontsourceVirtualModule(options?: FontsourceFonts) {
families = [],
} = options || {}
- for(const family of families) {
- if(typeof family === 'string') {
- source.push(`@import "@fontsource/${family.toLowerCase()}";`)
- } else {
- const {
- name,
- variables,
- weights,
- styles,
- subset
- } = family
-
- const subsetPrefix = subset ? `${subset}-` : ''
-
- if (variables) {
- if (weights) {
- console.warn('unplugin-fonts: Variable fonts do not support weights. Ignoring weights.')
- }
+ for (const family of families) {
+ if (!family)
+ continue
- for (const variable of variables) {
- source.push(`@import "@fontsource/${name.toLowerCase()}/${subsetPrefix}${variable}.css";`)
- }
- } else if (weights) {
- for (const weight of weights) {
- if (styles) {
- for (const style of styles) {
- if (style === 'normal') {
- source.push(`@import "@fontsource/${name.toLowerCase()}/${subsetPrefix}${style}.css";`)
- } else {
- source.push(`@import "@fontsource/${name.toLowerCase()}/${subsetPrefix}${weight}-${style}.css";`)
- }
- }
- } else {
- source.push(`@import "@fontsource/${name.toLowerCase()}/${subsetPrefix}${weight}.css";`)
+ if (typeof family === 'string') {
+ source.push(`@import "@fontsource/${family.toLowerCase()}";`)
+ continue
+ }
+ const {
+ name,
+ variables,
+ weights,
+ styles,
+ subset,
+ } = family
+
+ const subsetPrefix = subset ? `${subset}-` : ''
+
+ if (variables) {
+ if (weights)
+ console.warn('unplugin-fonts: Variable fonts does not support weights. Ignoring weights.')
+
+ for (const variable of variables)
+ source.push(`@import "@fontsource/${name.toLowerCase()}/${subsetPrefix}${variable}.css";`)
+ }
+ else if (weights) {
+ for (const weight of weights) {
+ if (styles) {
+ for (const style of styles) {
+ if (style === 'normal')
+ source.push(`@import "@fontsource/${name.toLowerCase()}/${subsetPrefix}${style}.css";`)
+ else
+ source.push(`@import "@fontsource/${name.toLowerCase()}/${subsetPrefix}${weight}-${style}.css";`)
}
}
- } else {
- if (subset) {
- source.push(`@import "@fontsource/${name.toLowerCase()}/${subset}.css";`)
- } else {
- source.push(`@import "@fontsource/${name.toLowerCase()}";`)
+ else {
+ source.push(`@import "@fontsource/${name.toLowerCase()}/${subsetPrefix}${weight}.css";`)
}
}
-
+ }
+ else {
+ if (subset)
+ source.push(`@import "@fontsource/${name.toLowerCase()}/${subset}.css";`)
+ else
+ source.push(`@import "@fontsource/${name.toLowerCase()}";`)
}
}
return source.join('\n')
-}
\ No newline at end of file
+}
diff --git a/src/loaders/google-fonts.ts b/src/loaders/google-fonts.ts
index e9bdd57..9a48763 100644
--- a/src/loaders/google-fonts.ts
+++ b/src/loaders/google-fonts.ts
@@ -1,20 +1,5 @@
import type { HtmlTagDescriptor } from 'vite'
-
-export interface GoogleFontFamily {
- name: string
- styles?: string
- defer?: boolean
-}
-export interface GoogleFonts {
- families: (string | GoogleFontFamily)[]
- text?: string
- display?: 'auto' | 'block' | 'swap' | 'fallback' | 'optional'
- preconnect?: boolean
- /**
- * @default: 'head-prepend'
- */
- injectTo?: 'head' | 'body' | 'head-prepend' | 'body-prepend'
-}
+import type { GoogleFonts } from '../types'
const GoogleFontsBase = 'https://fonts.googleapis.com/css2'
const GStaticBase = 'https://fonts.gstatic.com/'
@@ -43,7 +28,7 @@ export function googleLoader({
continue
}
- if (!(family as GoogleFontFamily))
+ if (!family)
continue
const {
diff --git a/src/loaders/index.ts b/src/loaders/index.ts
index 7f5837f..c13fe5b 100644
--- a/src/loaders/index.ts
+++ b/src/loaders/index.ts
@@ -1,18 +1,20 @@
-import { HtmlTagDescriptor } from 'vite'
+import type { HtmlTagDescriptor } from 'vite'
import type { Options } from '../types'
import { customLoader } from './custom'
import { typekitLoader } from './typekit'
import { googleLoader } from './google-fonts'
-export function getHeadLinkTags (resolvedOptions: Options, root: string) {
+export function getHeadLinkTags(resolvedOptions: Options, root: string) {
const tags: HtmlTagDescriptor[] = []
if (resolvedOptions.typekit)
tags.push(...typekitLoader(resolvedOptions.typekit))
+
if (resolvedOptions.google)
tags.push(...googleLoader(resolvedOptions.google))
+
if (resolvedOptions.custom)
tags.push(...customLoader(resolvedOptions.custom, root))
return tags
-}
\ No newline at end of file
+}
diff --git a/src/loaders/typekit.ts b/src/loaders/typekit.ts
index eeec414..79f17a6 100644
--- a/src/loaders/typekit.ts
+++ b/src/loaders/typekit.ts
@@ -1,13 +1,5 @@
import type { HtmlTagDescriptor } from 'vite'
-
-export interface TypeKitFonts {
- id: string
- defer?: boolean
- /**
- * default: 'head-prepend'
- */
- injectTo?: 'head' | 'body' | 'head-prepend' | 'body-prepend'
-}
+import type { TypeKitFonts } from '../types'
const TypekitFontBase = 'https://use.typekit.net/'
@@ -49,4 +41,3 @@ export function typekitLoader({
return tags
}
-
diff --git a/src/nuxt.ts b/src/nuxt.ts
index 0663c5c..bb44067 100644
--- a/src/nuxt.ts
+++ b/src/nuxt.ts
@@ -1,4 +1,4 @@
-import { addVitePlugin, addWebpackPlugin, defineNuxtModule, addTemplate } from '@nuxt/kit'
+import { addVitePlugin, addWebpackPlugin, defineNuxtModule } from '@nuxt/kit'
// Workaround for:
// src/nuxt.ts(5,1): error TS2742: The inferred type of 'default' cannot be named without a reference to '.pnpm/@nuxt+schema@3.0.0_rollup@3.7.3/node_modules/@nuxt/schema'. This is likely not portable. A type annotation is necessary.
import type {} from '@nuxt/schema'
diff --git a/src/types.ts b/src/types.ts
index f8ac812..9f5b69c 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -1,11 +1,145 @@
-import type { CustomFonts } from './loaders/custom'
-import type { FontsourceFonts } from './loaders/fontsource'
-import type { GoogleFonts } from './loaders/google-fonts'
-import type { TypeKitFonts } from './loaders/typekit'
-
export interface Options {
custom?: CustomFonts
fontsource?: FontsourceFonts
google?: GoogleFonts
typekit?: TypeKitFonts
}
+
+export interface CustomFontFace {
+ source: string
+ name: string
+ basename: string
+ weight: number
+ style: string
+ display: string
+ local?: string | string[]
+ files: {
+ src: string
+ ext: string
+ path: string
+ format: string
+ }[]
+}
+
+export interface CustomFontFamily {
+ /**
+ * Name of the font family.
+ * @example 'Comic Sans MS'
+ */
+ name: string
+
+ /**
+ * Regex(es) of font files to import. The names of the files will
+ * predicate the `font-style` and `font-weight` values of the `@font-rule`'s.
+ * @see https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight#common_weight_name_mapping
+ *
+ * @example
+ * A value of `./RobotoBoldItalic.*` will create this `@font-rule`:
+ *
+ * ```css
+ * font-face {
+ * font-family: 'Roboto';
+ * src: url(./RobotoBoldItalic.ttf) format('truetype')
+ * url(./RobotoBoldItalic.woff) format('woff')
+ * url(./RobotoBoldItalic.woff2) format('woff2');
+ * font-weight: bold;
+ * font-style: italic;
+ * font-display: auto;
+ * }
+ * ```
+ */
+ src: string | string[]
+ /**
+ * Local name of the font. Used to add `src: local()` to `@font-rule`.
+ * @see https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face#description
+ */
+ local?: string | string[]
+
+ /**
+ * Allows to transform the generated config for any font face.
+ *
+ * @param font
+ * @returns
+ */
+ transform?: (font: CustomFontFace) => CustomFontFace | null
+}
+
+export interface CustomFonts {
+ /**
+ * Font families.
+ */
+ families: CustomFontFamily[] | Record>
+
+ /**
+ * Defines the default `font-display` value used for the generated
+ * `@font-rule` classes.
+ * @see https://developer.mozilla.org/fr/docs/Web/CSS/@font-face/font-display
+ * @default 'auto'
+ */
+ display?: 'auto' | 'block' | 'swap' | 'fallback' | 'optional'
+
+ /**
+ * Using `` will trigger a request for the WebFont
+ * early in the critical rendering path, without having to wait for the
+ * CSSOM to be created.
+ * @see https://web.dev/optimize-webfont-loading/#preload-your-webfont-resources
+ * @default true
+ */
+ preload?: boolean
+
+ /**
+ * Using `` is intended for prefetching resources
+ * that will be used in the next navigation/page load
+ * (e.g. when you go to the next page)
+ *
+ * Note: this can not be used with `preload`
+ * @default false
+ */
+ prefetch?: boolean
+ /**
+ * @default: 'head-prepend'
+ */
+ injectTo?: 'head' | 'body' | 'head-prepend' | 'body-prepend'
+
+ /**
+ * Remove the prefix from the front path
+ * @default: 'public/'
+ */
+ stripPrefix?: string
+}
+
+export interface FontsourceFontFamily {
+ name: string
+ variables?: ('variable' | 'variable-italic' | 'variable-full' | 'variable-full-italic')[]
+ weights: (100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900)[]
+ styles?: ('italic' | 'normal')[]
+ subset?: string
+}
+export interface FontsourceFonts {
+ families: (string | FontsourceFontFamily)[]
+}
+
+export interface GoogleFontFamily {
+ name: string
+ styles?: string
+ defer?: boolean
+}
+export interface GoogleFonts {
+ families: (string | GoogleFontFamily)[]
+ text?: string
+ display?: 'auto' | 'block' | 'swap' | 'fallback' | 'optional'
+ preconnect?: boolean
+ /**
+ * @default: 'head-prepend'
+ */
+ injectTo?: 'head' | 'body' | 'head-prepend' | 'body-prepend'
+}
+
+export interface TypeKitFonts {
+ id: string
+ defer?: boolean
+ /**
+ * default: 'head-prepend'
+ */
+ injectTo?: 'head' | 'body' | 'head-prepend' | 'body-prepend'
+}
diff --git a/test/index.test.ts b/test/index.test.ts
new file mode 100644
index 0000000..e2079b8
--- /dev/null
+++ b/test/index.test.ts
@@ -0,0 +1,7 @@
+import { describe, expect, it } from 'vitest'
+
+describe('index', () => {
+ it('hi vitest', () => {
+ expect(1).toBe(1)
+ })
+})
diff --git a/tsup.config.ts b/tsup.config.ts
index c6495b2..0a63ae4 100644
--- a/tsup.config.ts
+++ b/tsup.config.ts
@@ -6,7 +6,7 @@ export default {
'src/astro/component.astro',
],
loader: {
- '.astro': 'copy'
+ '.astro': 'copy',
},
clean: true,
format: ['cjs', 'esm'],