chore: move to biome

This commit is contained in:
2026-01-09 16:42:55 -08:00
parent 2544a7d606
commit 4c7cfe4136
25 changed files with 2146 additions and 11818 deletions

View File

@@ -1,5 +1,3 @@
{
"recommendations": [
"Webnative.webnative"
]
"recommendations": ["Webnative.webnative"]
}

34
biome.json Normal file
View File

@@ -0,0 +1,34 @@
{
"$schema": "https://biomejs.dev/schemas/2.3.11/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true
},
"files": {
"ignoreUnknown": false
},
"formatter": {
"enabled": true,
"indentStyle": "tab"
},
"linter": {
"enabled": true,
"rules": {
"recommended": true
}
},
"javascript": {
"formatter": {
"quoteStyle": "double"
}
},
"assist": {
"enabled": true,
"actions": {
"source": {
"organizeImports": "on"
}
}
}
}

1788
bun.lock Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +1,9 @@
import type { CapacitorConfig } from '@capacitor/cli';
import type { CapacitorConfig } from "@capacitor/cli";
const config: CapacitorConfig = {
appId: 'io.ionic.starter',
appName: 'mobile',
webDir: 'dist'
appId: "io.ionic.starter",
appName: "mobile",
webDir: "dist",
};
export default config;

View File

@@ -1,10 +1,10 @@
import { defineConfig } from "cypress";
export default defineConfig({
e2e: {
baseUrl: "http://localhost:5173",
setupNodeEvents(on, config) {
// implement node event listeners here
},
},
});
e2e: {
baseUrl: "http://localhost:5173",
setupNodeEvents(on, config) {
// implement node event listeners here
},
},
});

View File

@@ -1,6 +1,6 @@
describe('My First Test', () => {
it('Visits the app root url', () => {
cy.visit('/')
cy.contains('ion-content', 'Tab 1 page')
})
})
describe("My First Test", () => {
it("Visits the app root url", () => {
cy.visit("/");
cy.contains("ion-content", "Tab 1 page");
});
});

View File

@@ -1,5 +1,5 @@
{
"name": "Using fixtures to represent data",
"email": "hello@cypress.io",
"body": "Fixtures are a great way to mock data for responses to routes"
"name": "Using fixtures to represent data",
"email": "hello@cypress.io",
"body": "Fixtures are a great way to mock data for responses to routes"
}

View File

@@ -34,4 +34,4 @@
// visit(originalFn: CommandOriginalFn, url: string, options: Partial<VisitOptions>): Chainable<Element>
// }
// }
// }
// }

View File

@@ -14,7 +14,7 @@
// ***********************************************************
// Import commands.js using ES2015 syntax:
import './commands'
import "./commands";
// Alternatively you can use CommonJS syntax:
// require('./commands')
// require('./commands')

View File

@@ -1,7 +1,7 @@
{
"name": "mobile",
"integrations": {
"capacitor": {}
},
"type": "react-vite"
"name": "mobile",
"integrations": {
"capacitor": {}
},
"type": "react-vite"
}

11512
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,54 +1,50 @@
{
"name": "mobile",
"private": true,
"version": "0.0.1",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"preview": "vite preview",
"test.e2e": "cypress run",
"test.unit": "vitest",
"lint": "eslint"
},
"dependencies": {
"@capacitor/app": "8.0.0",
"@capacitor/core": "8.0.0",
"@capacitor/haptics": "8.0.0",
"@capacitor/keyboard": "8.0.0",
"@capacitor/status-bar": "8.0.0",
"@ionic/react": "^8.5.0",
"@ionic/react-router": "^8.5.0",
"@types/react-router": "^5.1.20",
"@types/react-router-dom": "^5.3.3",
"ionicons": "^7.4.0",
"react": "19.0.0",
"react-dom": "19.0.0",
"react-router": "^5.3.4",
"react-router-dom": "^5.3.4"
},
"devDependencies": {
"@capacitor/cli": "8.0.0",
"@testing-library/dom": ">=7.21.4",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^16.2.0",
"@testing-library/user-event": "^14.4.3",
"@types/react": "19.0.10",
"@types/react-dom": "19.0.4",
"@vitejs/plugin-legacy": "^5.0.0",
"@vitejs/plugin-react": "^4.0.1",
"cypress": "^13.5.0",
"eslint": "^9.20.1",
"eslint-plugin-react": "^7.32.2",
"eslint-plugin-react-hooks": "^5.1.0",
"eslint-plugin-react-refresh": "^0.4.19",
"globals": "^15.15.0",
"jsdom": "^22.1.0",
"terser": "^5.4.0",
"typescript": "~5.9.0",
"typescript-eslint": "^8.24.0",
"vite": "^5.0.0",
"vitest": "^0.34.6"
},
"description": "An Ionic project"
"name": "mobile",
"private": true,
"version": "0.0.1",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"preview": "vite preview",
"test.e2e": "cypress run",
"test.unit": "vitest",
"lint": "biome check --write"
},
"dependencies": {
"@capacitor/app": "8.0.0",
"@capacitor/core": "8.0.0",
"@capacitor/haptics": "8.0.0",
"@capacitor/keyboard": "8.0.0",
"@capacitor/status-bar": "8.0.0",
"@ionic/react": "^8.5.0",
"@ionic/react-router": "^8.5.0",
"@types/react-router": "^5.1.20",
"@types/react-router-dom": "^5.3.3",
"ionicons": "^7.4.0",
"react": "19.0.0",
"react-dom": "19.0.0",
"react-router": "^5.3.4",
"react-router-dom": "^5.3.4"
},
"devDependencies": {
"@biomejs/biome": "2.3.11",
"@capacitor/cli": "8.0.0",
"@testing-library/dom": ">=7.21.4",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^16.2.0",
"@testing-library/user-event": "^14.4.3",
"@types/react": "19.0.10",
"@types/react-dom": "19.0.4",
"@vitejs/plugin-legacy": "^5.0.0",
"@vitejs/plugin-react": "^4.0.1",
"cypress": "^13.5.0",
"globals": "^15.15.0",
"jsdom": "^22.1.0",
"terser": "^5.4.0",
"typescript": "~5.9.0",
"vite": "^5.0.0",
"vitest": "^0.34.6"
},
"description": "An Ionic project"
}

View File

@@ -1,21 +1,21 @@
{
"short_name": "Ionic App",
"name": "My Ionic App",
"icons": [
{
"src": "assets/icon/favicon.png",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "assets/icon/icon.png",
"type": "image/png",
"sizes": "512x512",
"purpose": "maskable"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#ffffff",
"background_color": "#ffffff"
"short_name": "Ionic App",
"name": "My Ionic App",
"icons": [
{
"src": "assets/icon/favicon.png",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "assets/icon/icon.png",
"type": "image/png",
"sizes": "512x512",
"purpose": "maskable"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#ffffff",
"background_color": "#ffffff"
}

View File

@@ -1,8 +1,8 @@
import React from 'react';
import { render } from '@testing-library/react';
import App from './App';
import { render } from "@testing-library/react";
import React from "react";
import App from "./App";
test('renders without crashing', () => {
const { baseElement } = render(<App />);
expect(baseElement).toBeDefined();
test("renders without crashing", () => {
const { baseElement } = render(<App />);
expect(baseElement).toBeDefined();
});

View File

@@ -1,35 +1,35 @@
import { Redirect, Route } from 'react-router-dom';
import {
IonApp,
IonIcon,
IonLabel,
IonRouterOutlet,
IonTabBar,
IonTabButton,
IonTabs,
setupIonicReact
} from '@ionic/react';
import { IonReactRouter } from '@ionic/react-router';
import { ellipse, square, triangle } from 'ionicons/icons';
import Tab1 from './pages/Tab1';
import Tab2 from './pages/Tab2';
import Tab3 from './pages/Tab3';
IonApp,
IonIcon,
IonLabel,
IonRouterOutlet,
IonTabBar,
IonTabButton,
IonTabs,
setupIonicReact,
} from "@ionic/react";
import { IonReactRouter } from "@ionic/react-router";
import { ellipse, square, triangle } from "ionicons/icons";
import { Redirect, Route } from "react-router-dom";
import Tab1 from "./pages/Tab1";
import Tab2 from "./pages/Tab2";
import Tab3 from "./pages/Tab3";
/* Core CSS required for Ionic components to work properly */
import '@ionic/react/css/core.css';
import "@ionic/react/css/core.css";
/* Basic CSS for apps built with Ionic */
import '@ionic/react/css/normalize.css';
import '@ionic/react/css/structure.css';
import '@ionic/react/css/typography.css';
import "@ionic/react/css/normalize.css";
import "@ionic/react/css/structure.css";
import "@ionic/react/css/typography.css";
/* Optional CSS utils that can be commented out */
import '@ionic/react/css/padding.css';
import '@ionic/react/css/float-elements.css';
import '@ionic/react/css/text-alignment.css';
import '@ionic/react/css/text-transformation.css';
import '@ionic/react/css/flex-utils.css';
import '@ionic/react/css/display.css';
import "@ionic/react/css/padding.css";
import "@ionic/react/css/float-elements.css";
import "@ionic/react/css/text-alignment.css";
import "@ionic/react/css/text-transformation.css";
import "@ionic/react/css/flex-utils.css";
import "@ionic/react/css/display.css";
/**
* Ionic Dark Mode
@@ -40,48 +40,48 @@ import '@ionic/react/css/display.css';
/* import '@ionic/react/css/palettes/dark.always.css'; */
/* import '@ionic/react/css/palettes/dark.class.css'; */
import '@ionic/react/css/palettes/dark.system.css';
import "@ionic/react/css/palettes/dark.system.css";
/* Theme variables */
import './theme/variables.css';
import "./theme/variables.css";
setupIonicReact();
const App: React.FC = () => (
<IonApp>
<IonReactRouter>
<IonTabs>
<IonRouterOutlet>
<Route exact path="/tab1">
<Tab1 />
</Route>
<Route exact path="/tab2">
<Tab2 />
</Route>
<Route path="/tab3">
<Tab3 />
</Route>
<Route exact path="/">
<Redirect to="/tab1" />
</Route>
</IonRouterOutlet>
<IonTabBar slot="bottom">
<IonTabButton tab="tab1" href="/tab1">
<IonIcon aria-hidden="true" icon={triangle} />
<IonLabel>Tab 1</IonLabel>
</IonTabButton>
<IonTabButton tab="tab2" href="/tab2">
<IonIcon aria-hidden="true" icon={ellipse} />
<IonLabel>Tab 2</IonLabel>
</IonTabButton>
<IonTabButton tab="tab3" href="/tab3">
<IonIcon aria-hidden="true" icon={square} />
<IonLabel>Tab 3</IonLabel>
</IonTabButton>
</IonTabBar>
</IonTabs>
</IonReactRouter>
</IonApp>
<IonApp>
<IonReactRouter>
<IonTabs>
<IonRouterOutlet>
<Route exact path="/tab1">
<Tab1 />
</Route>
<Route exact path="/tab2">
<Tab2 />
</Route>
<Route path="/tab3">
<Tab3 />
</Route>
<Route exact path="/">
<Redirect to="/tab1" />
</Route>
</IonRouterOutlet>
<IonTabBar slot="bottom">
<IonTabButton tab="tab1" href="/tab1">
<IonIcon aria-hidden="true" icon={triangle} />
<IonLabel>Tab 1</IonLabel>
</IonTabButton>
<IonTabButton tab="tab2" href="/tab2">
<IonIcon aria-hidden="true" icon={ellipse} />
<IonLabel>Tab 2</IonLabel>
</IonTabButton>
<IonTabButton tab="tab3" href="/tab3">
<IonIcon aria-hidden="true" icon={square} />
<IonLabel>Tab 3</IonLabel>
</IonTabButton>
</IonTabBar>
</IonTabs>
</IonReactRouter>
</IonApp>
);
export default App;

View File

@@ -1,24 +1,24 @@
.container {
text-align: center;
position: absolute;
left: 0;
right: 0;
top: 50%;
transform: translateY(-50%);
text-align: center;
position: absolute;
left: 0;
right: 0;
top: 50%;
transform: translateY(-50%);
}
.container strong {
font-size: 20px;
line-height: 26px;
font-size: 20px;
line-height: 26px;
}
.container p {
font-size: 16px;
line-height: 22px;
color: #8c8c8c;
margin: 0;
font-size: 16px;
line-height: 22px;
color: #8c8c8c;
margin: 0;
}
.container a {
text-decoration: none;
}
text-decoration: none;
}

View File

@@ -1,16 +1,25 @@
import './ExploreContainer.css';
import "./ExploreContainer.css";
interface ContainerProps {
name: string;
name: string;
}
const ExploreContainer: React.FC<ContainerProps> = ({ name }) => {
return (
<div className="container">
<strong>{name}</strong>
<p>Explore <a target="_blank" rel="noopener noreferrer" href="https://ionicframework.com/docs/components">UI Components</a></p>
</div>
);
return (
<div className="container">
<strong>{name}</strong>
<p>
Explore{" "}
<a
target="_blank"
rel="noopener noreferrer"
href="https://ionicframework.com/docs/components"
>
UI Components
</a>
</p>
</div>
);
};
export default ExploreContainer;

View File

@@ -1,11 +1,11 @@
import React from 'react';
import { createRoot } from 'react-dom/client';
import App from './App';
import React from "react";
import { createRoot } from "react-dom/client";
import App from "./App";
const container = document.getElementById('root');
const container = document.getElementById("root");
const root = createRoot(container!);
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
<React.StrictMode>
<App />
</React.StrictMode>,
);

View File

@@ -1,25 +1,31 @@
import { IonContent, IonHeader, IonPage, IonTitle, IonToolbar } from '@ionic/react';
import ExploreContainer from '../components/ExploreContainer';
import './Tab1.css';
import {
IonContent,
IonHeader,
IonPage,
IonTitle,
IonToolbar,
} from "@ionic/react";
import ExploreContainer from "../components/ExploreContainer";
import "./Tab1.css";
const Tab1: React.FC = () => {
return (
<IonPage>
<IonHeader>
<IonToolbar>
<IonTitle>Tab 1</IonTitle>
</IonToolbar>
</IonHeader>
<IonContent fullscreen>
<IonHeader collapse="condense">
<IonToolbar>
<IonTitle size="large">Tab 1</IonTitle>
</IonToolbar>
</IonHeader>
<ExploreContainer name="Tab 1 page" />
</IonContent>
</IonPage>
);
return (
<IonPage>
<IonHeader>
<IonToolbar>
<IonTitle>Tab 1</IonTitle>
</IonToolbar>
</IonHeader>
<IonContent fullscreen>
<IonHeader collapse="condense">
<IonToolbar>
<IonTitle size="large">Tab 1</IonTitle>
</IonToolbar>
</IonHeader>
<ExploreContainer name="Tab 1 page" />
</IonContent>
</IonPage>
);
};
export default Tab1;

View File

@@ -1,25 +1,31 @@
import { IonContent, IonHeader, IonPage, IonTitle, IonToolbar } from '@ionic/react';
import ExploreContainer from '../components/ExploreContainer';
import './Tab2.css';
import {
IonContent,
IonHeader,
IonPage,
IonTitle,
IonToolbar,
} from "@ionic/react";
import ExploreContainer from "../components/ExploreContainer";
import "./Tab2.css";
const Tab2: React.FC = () => {
return (
<IonPage>
<IonHeader>
<IonToolbar>
<IonTitle>Tab 2</IonTitle>
</IonToolbar>
</IonHeader>
<IonContent fullscreen>
<IonHeader collapse="condense">
<IonToolbar>
<IonTitle size="large">Tab 2</IonTitle>
</IonToolbar>
</IonHeader>
<ExploreContainer name="Tab 2 page" />
</IonContent>
</IonPage>
);
return (
<IonPage>
<IonHeader>
<IonToolbar>
<IonTitle>Tab 2</IonTitle>
</IonToolbar>
</IonHeader>
<IonContent fullscreen>
<IonHeader collapse="condense">
<IonToolbar>
<IonTitle size="large">Tab 2</IonTitle>
</IonToolbar>
</IonHeader>
<ExploreContainer name="Tab 2 page" />
</IonContent>
</IonPage>
);
};
export default Tab2;

View File

@@ -1,25 +1,31 @@
import { IonContent, IonHeader, IonPage, IonTitle, IonToolbar } from '@ionic/react';
import ExploreContainer from '../components/ExploreContainer';
import './Tab3.css';
import {
IonContent,
IonHeader,
IonPage,
IonTitle,
IonToolbar,
} from "@ionic/react";
import ExploreContainer from "../components/ExploreContainer";
import "./Tab3.css";
const Tab3: React.FC = () => {
return (
<IonPage>
<IonHeader>
<IonToolbar>
<IonTitle>Tab 3</IonTitle>
</IonToolbar>
</IonHeader>
<IonContent fullscreen>
<IonHeader collapse="condense">
<IonToolbar>
<IonTitle size="large">Tab 3</IonTitle>
</IonToolbar>
</IonHeader>
<ExploreContainer name="Tab 3 page" />
</IonContent>
</IonPage>
);
return (
<IonPage>
<IonHeader>
<IonToolbar>
<IonTitle>Tab 3</IonTitle>
</IonToolbar>
</IonHeader>
<IonContent fullscreen>
<IonHeader collapse="condense">
<IonToolbar>
<IonTitle size="large">Tab 3</IonTitle>
</IonToolbar>
</IonHeader>
<ExploreContainer name="Tab 3 page" />
</IonContent>
</IonPage>
);
};
export default Tab3;

View File

@@ -2,13 +2,13 @@
// allows you to do things like:
// expect(element).toHaveTextContent(/react/i)
// learn more: https://github.com/testing-library/jest-dom
import '@testing-library/jest-dom/extend-expect';
import "@testing-library/jest-dom/extend-expect";
// Mock matchmedia
window.matchMedia = window.matchMedia || function() {
return {
matches: false,
addListener: function() {},
removeListener: function() {}
};
};
window.matchMedia =
window.matchMedia ||
(() => ({
matches: false,
addListener: () => {},
removeListener: () => {},
}));

View File

@@ -1,21 +1,21 @@
{
"compilerOptions": {
"target": "ESNext",
"useDefineForClassFields": true,
"lib": ["DOM", "DOM.Iterable", "ESNext"],
"allowJs": false,
"skipLibCheck": true,
"esModuleInterop": false,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "ESNext",
"moduleResolution": "Node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx"
},
"include": ["src"],
"references": [{ "path": "./tsconfig.node.json" }]
"compilerOptions": {
"target": "ESNext",
"useDefineForClassFields": true,
"lib": ["DOM", "DOM.Iterable", "ESNext"],
"allowJs": false,
"skipLibCheck": true,
"esModuleInterop": false,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "ESNext",
"moduleResolution": "Node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx"
},
"include": ["src"],
"references": [{ "path": "./tsconfig.node.json" }]
}

View File

@@ -1,9 +1,9 @@
{
"compilerOptions": {
"composite": true,
"module": "ESNext",
"moduleResolution": "Node",
"allowSyntheticDefaultImports": true
},
"include": ["vite.config.ts"]
"compilerOptions": {
"composite": true,
"module": "ESNext",
"moduleResolution": "Node",
"allowSyntheticDefaultImports": true
},
"include": ["vite.config.ts"]
}

View File

@@ -1,18 +1,15 @@
/// <reference types="vitest" />
import legacy from '@vitejs/plugin-legacy'
import react from '@vitejs/plugin-react'
import { defineConfig } from 'vite'
import legacy from "@vitejs/plugin-legacy";
import react from "@vitejs/plugin-react";
import { defineConfig } from "vite";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
react(),
legacy()
],
test: {
globals: true,
environment: 'jsdom',
setupFiles: './src/setupTests.ts',
}
})
plugins: [react(), legacy()],
test: {
globals: true,
environment: "jsdom",
setupFiles: "./src/setupTests.ts",
},
});