diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
new file mode 100644
index 0000000..22f970f
--- /dev/null
+++ b/.github/workflows/test.yml
@@ -0,0 +1,35 @@
+# This workflow will do a clean install of node dependencies, cache/restore them, build the source code and run tests across different versions of node
+# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
+
+name: Test
+
+on:
+ push:
+ branches: [main, dev]
+ pull_request:
+ branches: [main]
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ node-version: [20.x]
+ # See supported Node.js release schedule at https://nodejs.org/en/about/releases/
+ steps:
+ - uses: actions/checkout@v4
+ - name: Use Node.js ${{ matrix.node-version }}
+ uses: actions/setup-node@v4
+ with:
+ node-version: ${{ matrix.node-version }}
+ - name: test
+ run: |
+ yarn
+ yarn build
+ yarn test
+ # yarn test --coverage
+ # - name: report
+ # uses: coverallsapp/github-action@v1.0.1
+ # with:
+ # github-token: ${{ secrets.GITHUB_TOKEN }}
+ # path-to-lcov: ./coverage/lcov.info
diff --git a/lerna.json b/lerna.json
index 65827c7..5b309a4 100644
--- a/lerna.json
+++ b/lerna.json
@@ -1,12 +1,12 @@
{
"version": "independent",
"npmClient": "yarn",
- "useWorkspaces": true,
"packages": ["packages/*"],
"ignoreChanges": [
"**/docs/**",
"**/fixtures/**",
"**/__tests__/**",
+ "**/__snapshots__/**",
"**/test/**",
"**/*.mdx",
"**/*.md"
diff --git a/packages/reiconify-loader/README.md b/packages/reiconify-loader/README.md
index afb73b0..8d0de5d 100644
--- a/packages/reiconify-loader/README.md
+++ b/packages/reiconify-loader/README.md
@@ -16,8 +16,15 @@ module.exports = {
oneOf: [
{
resourceQuery: /react/,
- use: 'reiconify-loader',
+ use: {
+ loader: 'reiconify-loader',
+ // whether to use React Native
+ // options: {
+ // native: true,
+ // },
+ },
},
+ // optional fallback
{
use: 'file-loader',
},
@@ -31,8 +38,12 @@ module.exports = {
Import icons:
```js
+// types for web
///
+// types for React Native
+///
+
// import React icon
import AlarmIcon from './icons/alarm.svg?react'
diff --git a/packages/reiconify-loader/index.ts b/packages/reiconify-loader/index.ts
index 979d0e7..4a43f64 100644
--- a/packages/reiconify-loader/index.ts
+++ b/packages/reiconify-loader/index.ts
@@ -2,9 +2,15 @@ import type {LoaderContext} from 'webpack'
import {callbackify} from 'util'
import transform from 'reiconify/lib/transform'
+/**
+ * SVG to React Component loader
+ */
export default function reiconifyLoader(
- this: LoaderContext<{}>,
+ this: LoaderContext<{native?: boolean}>,
source: string
) {
- callbackify(() => transform(source, {baseName: 'base-icon'}))(this.async())
+ const {native} = this.getOptions()
+ callbackify(() =>
+ transform(source, native ? {native} : {baseName: 'base-icon'})
+ )(this.async())
}
diff --git a/packages/reiconify-loader/native.d.ts b/packages/reiconify-loader/native.d.ts
new file mode 100644
index 0000000..b603fd0
--- /dev/null
+++ b/packages/reiconify-loader/native.d.ts
@@ -0,0 +1,6 @@
+import type {SvgProps} from 'react-native-svg'
+
+declare module '*?react' {
+ const Icon: React.FC
+ export default Icon
+}
diff --git a/packages/reiconify-loader/package.json b/packages/reiconify-loader/package.json
index 893b834..e4dab29 100644
--- a/packages/reiconify-loader/package.json
+++ b/packages/reiconify-loader/package.json
@@ -12,6 +12,7 @@
"license": "MIT",
"files": [
"client.d.ts",
+ "native.d.ts",
"dist"
],
"jest": {
@@ -27,9 +28,17 @@
"base-icon": "^2.2.1"
},
"peerDependencies": {
- "webpack": "^4 || ^5"
+ "webpack": "^4 || ^5",
+ "react": "*",
+ "react-native-svg": "*"
+ },
+ "peerDependenciesMeta": {
+ "react-native-svg": {
+ "optional": true
+ }
},
"devDependencies": {
+ "identity-obj-proxy": "^3.0.0",
"memfs": "^3.4.7",
"webpack": "^5.74.0"
}
diff --git a/packages/reiconify-loader/test/__snapshots__/index.spec.ts.snap b/packages/reiconify-loader/test/__snapshots__/index.spec.ts.snap
index 2018bd9..635b392 100644
--- a/packages/reiconify-loader/test/__snapshots__/index.spec.ts.snap
+++ b/packages/reiconify-loader/test/__snapshots__/index.spec.ts.snap
@@ -19,3 +19,22 @@ export {
};
"
`;
+
+exports[`compiler svg for RN 1`] = `
+"var __assign = Object.assign;
+import React from "react";
+import * as svg from "react-native-svg";
+function Icon(props) {
+ return /* @__PURE__ */ React.createElement(svg.Svg, __assign(__assign({
+ width: "24",
+ height: "24",
+ viewBox: "0 0 24 24"
+ }, props), size && {width: size, height: size}), /* @__PURE__ */ React.createElement(svg.Path, {
+ d: "M9 16.17 4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"
+ }));
+}
+export {
+ Icon as default
+};
+"
+`;
diff --git a/packages/reiconify-loader/test/compiler.ts b/packages/reiconify-loader/test/compiler.ts
index 92554ec..43073c7 100644
--- a/packages/reiconify-loader/test/compiler.ts
+++ b/packages/reiconify-loader/test/compiler.ts
@@ -3,7 +3,7 @@ import webpack from 'webpack'
import {createFsFromVolume, Volume} from 'memfs'
// https://webpack.js.org/contribute/writing-a-loader/#testing
-export default function compiler(fixture) {
+export default function compiler(fixture, native = false) {
const compiler = webpack({
context: __dirname,
entry: `./${fixture}`,
@@ -18,6 +18,12 @@ export default function compiler(fixture) {
path: path.resolve(__dirname),
filename: 'bundle.js',
},
+ resolve: {
+ alias: {
+ // skip installing react-native-svg and react-native
+ 'react-native-svg': 'identity-obj-proxy',
+ },
+ },
module: {
rules: [
{
@@ -25,7 +31,12 @@ export default function compiler(fixture) {
oneOf: [
{
resourceQuery: /react/,
- use: require.resolve('../index.ts'),
+ use: {
+ loader: require.resolve('../index.ts'),
+ options: {
+ native,
+ },
+ },
},
],
},
diff --git a/packages/reiconify-loader/test/index.spec.ts b/packages/reiconify-loader/test/index.spec.ts
index 14d5b0f..9f62248 100644
--- a/packages/reiconify-loader/test/index.spec.ts
+++ b/packages/reiconify-loader/test/index.spec.ts
@@ -5,3 +5,9 @@ test('compiler svg', async () => {
const output = stats.toJson({source: true})?.modules?.[0]?.modules?.[0].source
expect(output).toMatchSnapshot()
})
+
+test('compiler svg for RN', async () => {
+ const stats = await compiler('./icons/check.svg?react', true)
+ const output = stats.toJson({source: true})?.modules?.[0]?.modules?.[0].source
+ expect(output).toMatchSnapshot()
+})
diff --git a/packages/reiconify/lib/defaultConfig.js b/packages/reiconify/lib/defaultConfig.js
index c943e15..a3aa7f3 100644
--- a/packages/reiconify/lib/defaultConfig.js
+++ b/packages/reiconify/lib/defaultConfig.js
@@ -1,6 +1,20 @@
const pascalCase = require('pascal-case')
const template = (data) => {
+ if (data.native) {
+ const jsxWithProps = data.jsxString.replace(
+ /