# MDev

> In-browser developer tools built with TypeScript, vanilla DOM APIs, and Shadow DOM isolation.

[![npm version](https://img.shields.io/npm/v/@moo-m/mdev.svg)](https://www.npmjs.com/package/@moo-m/mdev)
[![npm downloads](https://img.shields.io/npm/dm/@moo-m/mdev.svg)](https://www.npmjs.com/package/@moo-m/mdev)
[![license](https://img.shields.io/npm/l/@moo-m/mdev.svg)](#license)
[![TypeScript](https://img.shields.io/badge/TypeScript-ready-blue.svg)](https://www.typescriptlang.org/)
[![Bundle Size](https://img.shields.io/bundlephobia/minzip/@moo-m/mdev.svg)](https://bundlephobia.com/package/@moo-m/mdev)
[![jsDelivr](https://data.jsdelivr.com/v1/package/npm/@moo-m/mdev/badge)](https://www.jsdelivr.com/package/npm/@moo-m/mdev)
[![GitHub stars](https://img.shields.io/github/stars/moo-m/MDev.svg?style=social)](https://github.com/moo-m/MDev)

MDev is an embedded, framework-agnostic developer toolbar for inspecting and debugging web pages directly inside the browser. It is especially useful where native DevTools are unavailable: mobile browsers, embedded WebViews, smart TVs, and staging environments.

**Website and documentation:** https://moo-m.github.io/mdevweb/

## Table of Contents

- [Key Features](#key-features)
- [Installation](#installation)
- [Quick Start](#quick-start)
- [Usage in Frameworks](#usage-in-frameworks)
- [Using MDev in Development Only](#using-mdev-in-development-only)
- [Window Controls](#window-controls)
- [Modules](#modules)
- [API Reference](#api-reference)
- [Global State](#global-state)
- [Browser Support](#browser-support)
- [Notes and Limitations](#notes-and-limitations)
- [Troubleshooting](#troubleshooting)
- [Contributing](#contributing)
- [Changelog](#changelog)
- [Links](#links)
- [License](#license)

## Key Features

- **No external UI dependencies.** Built with TypeScript and native Web APIs, with no UI framework.
- **Shadow DOM isolation.** The MDev UI is isolated from the host page, so your site's CSS cannot break it and it cannot break your site.
- **Mobile and touch friendly.** Floating windows you can move, resize, hide, and close, with two-finger gestures on touch screens.
- **Console app.** Color-coded logging, conditional output (`test`), timers (`time` / `timeEnd`), and an object tree viewer.
- **Elements inspector.** A live tree of the DOM, kept in sync with the page through `MutationObserver`.
- **Application manager.** Manage `localStorage`, `sessionStorage`, and cookies. Browse IndexedDB, Cache Storage, and Service Workers.
- **Sources explorer.** Search, preview, copy, or download scripts, styles, images, media, and fonts.

## Installation

### npm

```bash
npm install @moo-m/mdev
```


### CDN

For quick tests or static HTML pages without a bundler:

```html
<script type="module">
  import 'https://cdn.jsdelivr.net/npm/@moo-m/mdev/MDev.js';
</script>
```

Pin a specific version to avoid unexpected changes:

```html
<script type="module">
  import 'https://cdn.jsdelivr.net/npm/@moo-m/mdev@1.0.0/MDev.js';
</script>
```

## Quick Start

Import the package once in your application entry file:

```ts
import '@moo-m/mdev';

// MDev creates its floating dock on the page automatically.
```

Then use the dock to open **Console**, **Elements**, **Application**, or **Sources**, and call the logging helpers from anywhere in your code:

```ts
// Color-coded logs
green('Success:', 'Data fetched successfully');
red('Error:', 'Failed to load user profile');
blue('Info:', 'Session renewed');
yellow('Warning:', 'Storage usage is close to the quota');

// Conditional output
test(users.length > 0, 'Users list loaded', users);

// Timing
time('DataRender');
// ... heavy work ...
timeEnd('DataRender');

// Clear the MDev console
clear();
```

The helpers are also available on `window`:

```ts
window.red('Something went wrong');
```

### Printing from any value

You can also print directly from any value by calling the helper as a method on it. The same methods (`green`, `red`, `blue`, `yellow`, ...) exist on every data type:

```ts
'Saved successfully'.green();       // string
(404).red();                        // number
true.blue();                        // boolean
[1, 2, 3].yellow();                 // array
({ id: 1, name: 'Sara' }).green();  // object
user.name.blue();                   // any property or variable
```

This is handy for logging in the middle of an expression without a separate statement. Use whichever style fits: global function, `window.*`, or a method on the value.

> **TypeScript:** if your compiler reports that `green`, `red`, etc. are not defined, access them through `window` or add a global declaration file (for example `mdev.d.ts`) that declares them.

## Usage in Frameworks

MDev is framework-agnostic. Import it once in your entry file, before or after your app mounts.

**React / Vite**

```tsx
// src/main.tsx
import '@moo-m/mdev';
import { createRoot } from 'react-dom/client';
import App from './App';

createRoot(document.getElementById('root')!).render(<App />);
```

**Vue**

```ts
// src/main.ts
import '@moo-m/mdev';
import { createApp } from 'vue';
import App from './App.vue';

createApp(App).mount('#app');
```

**Plain HTML**

```html
<script type="module">
  import 'https://cdn.jsdelivr.net/npm/@moo-m/mdev/MDev.js';
</script>
```

## Using MDev in Development Only

MDev is designed for development and testing. Load it conditionally so it never reaches production users:

```ts
// Vite
if (import.meta.env.DEV) {
  await import('@moo-m/mdev');
}
```

```ts
// Webpack / Node-based bundlers
if (process.env.NODE_ENV !== 'production') {
  await import('@moo-m/mdev');
}
```

```ts
// Staging only, via a query flag
if (location.search.includes('mdev=1')) {
  await import('@moo-m/mdev');
}
```

## Window Controls

Every app opens in its own floating window.

| Action | How |
| --- | --- |
| Resize | Drag the bottom-right corner, or pinch with two fingers on a touch screen |
| Move | Drag the window with two fingers, or by its title bar |
| Show / hide | Tap the app icon in the dock |
| Close | Tap **x** at the top right of the window |

## Modules

### Console (`c`)

- **Custom logging:** `green`, `red`, `blue`, `yellow`, `test`, `time`, `timeEnd`.
- **Data formatter:** primitives, arrays, and objects are shown as expandable trees.
- **Detached inspection:** open large objects in their own window.
- **Filter bar:** filter by success, error, warn, info, test, or time.

### Elements (`e`)

- **Abstract Data Tree (ADT):** converts the document into a nested structure of tags, attributes, text, and comments.
- **Live tracking:** `MutationObserver` follows attribute changes, added or removed nodes, and text changes.
- **Tag and attribute viewer:** shows tag names, IDs, classes, and other attributes.

### Application (`a`)

- **localStorage and sessionStorage:** view, search, add, edit, and delete items, with confirmation before destructive actions.
- **Cookies:** read, add, and delete cookies available to `document.cookie`.
- **IndexedDB:** browse databases, object stores, record counts, and records as formatted JSON.
- **Cache and Service Workers:** list cache names and Service Worker registrations, including scope, script URL, and state.

### Sources (`s`)

- **Resource collector:** the document, inline and external scripts, styles, images, audio, video, and fonts.
- **Previewer:** text and code, images, and native audio and video controls.
- **Export:** copy text content to the clipboard or download it as a file.

## API Reference

All helpers are global functions (also available on `window`).

| Method | Type | Description |
| --- | --- | --- |
| `green(...data)` | success | Logs a success message. |
| `red(...data)` | error | Logs an error message. |
| `blue(...data)` | info | Logs an informational message. |
| `yellow(...data)` | warn | Logs a warning. |
| `test(condition, ...data)` | test | Shows the data when `condition` is truthy. |
| `time(label)` | time | Records the start of a timer. |
| `timeEnd(label)` | time | Records the end of a timer. |
| `clear()` | n/a | Clears the displayed and stored messages. |

### Printing methods

Every logging helper can be called in three ways:

| Style | Example |
| --- | --- |
| Global function | `green('Done')` |
| On `window` | `window.green('Done')` |
| As a method on any data type | `'Done'.green()`, `(42).red()`, `[1, 2].blue()`, `({ a: 1 }).yellow()` |

The method form is available on any value through non-enumerable `Object.prototype` properties (see [Notes and Limitations](#notes-and-limitations)).

## Global State

MDev keeps its state on `window.MDev`:

```ts
interface MDevGlobal {
  host: ShadowRoot | null;

  screens: {
    console:     { activate: boolean };
    elements:    { activate: boolean };
    application: { activate: boolean };
    sources:     { activate: boolean };
  };
}
```

| Property | Description |
| --- | --- |
| `host` | The Shadow DOM root that contains the MDev UI, or `null` before initialization. |
| `screens.<name>.activate` | Whether the given app window is currently active. |

## Browser Support

MDev targets modern browsers that support ES modules, Shadow DOM, and `MutationObserver`, including current versions of Chrome, Edge, Firefox, Safari, and their mobile and WebView counterparts.

## Notes and Limitations

- The logging helpers are also added to `Object.prototype` as non-enumerable properties, so `value.green()` works. Keep this in mind if you use libraries that rely on native prototypes.
- The native `console.log` is not forwarded to the MDev console. Use the MDev helpers above.
- Cookies are limited by the browser. `HttpOnly` cookies cannot be read from JavaScript.
- Cross-origin sources need valid CORS headers to be previewed. Otherwise, they may be listed as unavailable.
- Cache Storage and Service Workers are read-only for now.
- MDev is designed for development and testing. Keep it out of your production build (see [Using MDev in Development Only](#using-mdev-in-development-only)).

## Troubleshooting

**The dock does not appear.**
Make sure the package is imported once in your entry file and that the code runs in a browser, not during server-side rendering. In SSR frameworks, import it inside a client-only block.

**`green` / `red` is not defined (TypeScript).**
Use `window.green(...)` or add a global type declaration for the helpers.

**Some sources show as unavailable.**
The resource is cross-origin and does not send CORS headers.

**My `console.log` output is missing.**
MDev does not forward the native console. Use `green`, `red`, `blue`, or `yellow`.

## Contributing

Issues and pull requests are welcome.

1. Fork the repository and create a branch.
2. Make your changes and test them in a browser.
3. Open a pull request describing the change.

Report bugs or suggest features at https://github.com/moo-m/MDev/issues.

## Changelog

See [GitHub Releases](https://github.com/moo-m/MDev/releases) for version history.

## Links

- Website: https://moo-m.github.io/mdevweb/
- npm: https://www.npmjs.com/package/@moo-m/mdev
- GitHub: https://github.com/moo-m/MDev
- Issues and suggestions: https://github.com/moo-m/MDev/issues
- jsDelivr: https://www.jsdelivr.com/package/npm/@moo-m/mdev

## License

[ISC](./LICENSE)
