mevebu 1.7.2 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +179 -128
- package/mevebu/app/mevebu.js +111 -23
- package/mevebu/app/tailwind.css +65 -6
- package/mevebu/libs/js/core.js +1 -1
- package/mevebu/libs/js/icons.js +6 -1
- package/mevebu/libs/js/registry.js +19 -0
- package/mevebu/libs/js/tools/image-converter.js +643 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,36 +1,61 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
1
3
|
# mevebu
|
|
2
4
|
|
|
3
|
-
**
|
|
5
|
+
**187 free browser tools, one page each. No sign up. No uploads. Everything runs in your tab.**
|
|
4
6
|
|
|
5
|
-
A
|
|
6
|
-
hash a text, sign a token, format JSON, pick a color, run a timer, count words,
|
|
7
|
-
build a cron line, check a JWT, read a QR. Every tool opens on its own page and
|
|
8
|
-
most of them update as you type, so there is no submit button and no waiting.
|
|
7
|
+
A private toolbox for the small jobs that do not deserve a whole app: format JSON, decode a JWT, make a password, build a cron line, pick a color, scan a QR code, and a lot more.
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
[](https://www.npmjs.com/package/mevebu)
|
|
10
|
+
[](https://www.npmjs.com/package/mevebu)
|
|
11
|
+
[](./LICENSE)
|
|
12
|
+
[](https://github.com/mevebu/mevebu/stargazers)
|
|
13
|
+

|
|
14
|
+

|
|
12
15
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
[Quick start](#quick-start) · [What's inside](#whats-inside) · [Privacy](#privacy-by-design) · [Host it yourself](#host-it-yourself) · [Development](#development) · [FAQ](#faq)
|
|
17
|
+
|
|
18
|
+
</div>
|
|
19
|
+
|
|
20
|
+
<!-- Tip: add a screenshot here, for example:  -->
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## What is mevebu?
|
|
25
|
+
|
|
26
|
+
mevebu is a collection of **187 small online tools** that all run **inside your browser**. Each tool lives on its own page, does one job, and does it fast. Most of them update as you type, so there is no submit button and no waiting.
|
|
27
|
+
|
|
28
|
+
Think of it as a clean, private alternative to the usual "free online tools" websites. There are no accounts, no ads in your way, no uploads, and no tracking. Your text, passwords, tokens, and files stay on your device.
|
|
29
|
+
|
|
30
|
+
You can run it on your own computer with one command, or copy the folder to any static host and use it from anywhere.
|
|
31
|
+
|
|
32
|
+
## Why you will like it
|
|
19
33
|
|
|
20
|
-
|
|
34
|
+
- **Private by design.** Nothing you paste ever leaves your browser tab.
|
|
35
|
+
- **No account, no sign up.** Open a tool and use it.
|
|
36
|
+
- **Fast.** Plain HTML and vanilla JavaScript. No heavy framework, no loading spinners.
|
|
37
|
+
- **One tool, one page.** Every tool has its own clean page you can bookmark.
|
|
38
|
+
- **Instant search.** Press `Ctrl+K` and find any tool by name, keyword, or what it does.
|
|
39
|
+
- **Works offline.** Once installed, it runs fully on your machine.
|
|
40
|
+
- **Easy to host.** It is a plain static site. Drop it on any file host.
|
|
41
|
+
- **Free and open source.** MIT licensed.
|
|
21
42
|
|
|
22
|
-
|
|
43
|
+
## Quick start
|
|
44
|
+
|
|
45
|
+
You need [Node.js](https://nodejs.org) installed. Then run:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
23
48
|
npm install -g mevebu
|
|
24
49
|
mevebu
|
|
25
50
|
```
|
|
26
51
|
|
|
27
|
-
|
|
28
|
-
any free port), opens your browser to the home page, and serves the static
|
|
29
|
-
folder bundled with the package. Press `Ctrl+C` in the terminal to stop it.
|
|
52
|
+
That is it. mevebu starts a small local server, opens your browser on the home page, and serves the tools that ship with the package. Press `Ctrl+C` in the terminal to stop it.
|
|
30
53
|
|
|
31
|
-
|
|
54
|
+
mevebu tries port `5555` first, then `5678`, then `5432`, and finally any free port. The first three are stable between restarts, so your bookmarks keep working.
|
|
32
55
|
|
|
33
|
-
|
|
56
|
+
### CLI options
|
|
57
|
+
|
|
58
|
+
```text
|
|
34
59
|
-p, --port <number> Try this port first (5555, 5678, 5432 otherwise).
|
|
35
60
|
-d, --dir <path> Folder to serve. Defaults to the bundled tools.
|
|
36
61
|
--no-open Do not open the browser.
|
|
@@ -38,98 +63,86 @@ folder bundled with the package. Press `Ctrl+C` in the terminal to stop it.
|
|
|
38
63
|
-h, --help Print this help and exit.
|
|
39
64
|
```
|
|
40
65
|
|
|
41
|
-
The first three ports are stable across restarts, so the bookmark to your tools
|
|
42
|
-
page keeps working.
|
|
43
|
-
|
|
44
66
|
## What's inside
|
|
45
67
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
|
50
|
-
|
|
|
51
|
-
|
|
|
52
|
-
|
|
|
53
|
-
|
|
|
54
|
-
|
|
|
55
|
-
|
|
|
56
|
-
|
|
|
57
|
-
|
|
|
58
|
-
|
|
|
59
|
-
|
|
|
60
|
-
|
|
|
61
|
-
|
|
|
62
|
-
|
|
|
63
|
-
|
|
|
64
|
-
|
|
|
65
|
-
|
|
|
66
|
-
|
|
|
67
|
-
|
|
|
68
|
-
|
|
|
69
|
-
|
|
|
70
|
-
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
The full list is at the home page and under each category.
|
|
93
|
-
|
|
94
|
-
## How it stays private
|
|
95
|
-
|
|
96
|
-
Every tool is a static HTML file, a tiny JavaScript module, and a Lucide icon.
|
|
97
|
-
The HTML and the JavaScript are served from your machine when you run `mevebu`,
|
|
98
|
-
or from the file you host when you copy the `mevebu/` folder somewhere. There is
|
|
99
|
-
no server-side code, no analytics, and no API key.
|
|
68
|
+
mevebu has **187 tools in 20 categories**. Here is the full breakdown:
|
|
69
|
+
|
|
70
|
+
| Category | Tools |
|
|
71
|
+
| ------------------ | ----: |
|
|
72
|
+
| Random | 3 |
|
|
73
|
+
| Passwords and keys | 10 |
|
|
74
|
+
| Developer | 21 |
|
|
75
|
+
| Convert | 4 |
|
|
76
|
+
| Text and data | 14 |
|
|
77
|
+
| Daily use | 8 |
|
|
78
|
+
| Math | 17 |
|
|
79
|
+
| Date and time | 7 |
|
|
80
|
+
| Data and lists | 8 |
|
|
81
|
+
| Design | 10 |
|
|
82
|
+
| Web and SEO | 12 |
|
|
83
|
+
| Encoding | 8 |
|
|
84
|
+
| Academic | 15 |
|
|
85
|
+
| Study | 7 |
|
|
86
|
+
| Business | 10 |
|
|
87
|
+
| Locale | 7 |
|
|
88
|
+
| Content | 8 |
|
|
89
|
+
| GitHub | 8 |
|
|
90
|
+
| Units | 8 |
|
|
91
|
+
| QR codes | 2 |
|
|
92
|
+
| **Total** | **187** |
|
|
93
|
+
|
|
94
|
+
The counts come straight from the tool registry, so this table and the app never drift apart.
|
|
95
|
+
|
|
96
|
+
### Popular tools
|
|
97
|
+
|
|
98
|
+
| Tool | What it does |
|
|
99
|
+
| ---- | ------------ |
|
|
100
|
+
| **Password generator** | Make a strong password and copy it. The page only talks to your clipboard. |
|
|
101
|
+
| **JSON formatter** | Paste your JSON and get a clean, formatted version as you type. |
|
|
102
|
+
| **JWT generator and decoder** | Sign a token with HS256, RS256, or ES256, or paste one and read its header and payload. |
|
|
103
|
+
| **Color palette** | Pick one color and get matching analogous, complementary, or monochrome schemes. |
|
|
104
|
+
| **Countdown timer** | A quiet, fullscreen timer that keeps running when the tab is hidden. |
|
|
105
|
+
| **QR code generator** | Turn a URL, a Wi-Fi config, or any text into a scannable image. |
|
|
106
|
+
| **Slug converter** | Turn a sentence into a clean, readable URL slug. |
|
|
107
|
+
|
|
108
|
+
Browse everything from the home page or by category, or just press `Ctrl+K` and start typing.
|
|
109
|
+
|
|
110
|
+
## Privacy by design
|
|
111
|
+
|
|
112
|
+
mevebu is built so that your data has nowhere to go. Every tool is a static HTML file, a tiny JavaScript module, and a Lucide icon. There is no server side code, no analytics, and no API key.
|
|
100
113
|
|
|
101
114
|
When you paste a password, a token, or a CSV into a tool:
|
|
102
115
|
|
|
103
|
-
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
##
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
Tailwind built from one source file, and there is no separate build step. The
|
|
128
|
-
hosting layer never runs code on your behalf.
|
|
116
|
+
- It is processed in your browser tab, using the standard Web Crypto API or other built-in browser APIs.
|
|
117
|
+
- Nothing is sent to a remote server, because there is no remote server in the loop.
|
|
118
|
+
- Nothing is saved to disk by the tool.
|
|
119
|
+
- The only network request the page makes is to load itself and to read the GitHub star count for the footer chip. That request fails quietly when you are offline.
|
|
120
|
+
|
|
121
|
+
Do not just take our word for it. Open the Network tab in your browser dev tools and watch a tool work. You will not see an upload.
|
|
122
|
+
|
|
123
|
+
| | mevebu | Typical online tool sites |
|
|
124
|
+
| --- | :---: | :---: |
|
|
125
|
+
| Account needed | No | Often |
|
|
126
|
+
| Your data uploaded | Never | Sometimes |
|
|
127
|
+
| Works offline | Yes | Rarely |
|
|
128
|
+
| Open source | Yes (MIT) | Rarely |
|
|
129
|
+
| Self-hostable | Yes | Rarely |
|
|
130
|
+
|
|
131
|
+
## Host it yourself
|
|
132
|
+
|
|
133
|
+
Prefer not to use the CLI? mevebu is a plain static site, so you can host it anywhere files can be served: a static site host, a CDN, an object store, or even a USB drive.
|
|
134
|
+
|
|
135
|
+
1. Copy the `mevebu/` folder from this repo (or from the npm package).
|
|
136
|
+
2. Upload it to your host.
|
|
137
|
+
3. Open `index.html`.
|
|
138
|
+
|
|
139
|
+
Routes are hash routes, like `#/security/password-generator`, so you do not need any server rewrites. The CSS is one committed stylesheet built by Tailwind, and there is no extra build step. Your host never has to run code.
|
|
129
140
|
|
|
130
141
|
## Development
|
|
131
142
|
|
|
132
|
-
|
|
143
|
+
Want to hack on mevebu or add your own tool? Here is how to get started:
|
|
144
|
+
|
|
145
|
+
```bash
|
|
133
146
|
git clone https://github.com/mevebu/mevebu
|
|
134
147
|
cd mevebu
|
|
135
148
|
npm install
|
|
@@ -138,38 +151,76 @@ npm run icons # regenerate the vendored Lucide icon set
|
|
|
138
151
|
npm start # serve the static folder on http://localhost:5555
|
|
139
152
|
```
|
|
140
153
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
154
|
+
### Project layout
|
|
155
|
+
|
|
156
|
+
```text
|
|
157
|
+
bin/ The mevebu command line entry
|
|
158
|
+
mevebu/ The static app that gets served
|
|
159
|
+
app/ App shell (mevebu.js) and the Tailwind source (tailwind.src.css)
|
|
160
|
+
libs/js/ Shared core.js, the registry, and one file per tool in tools/
|
|
161
|
+
scripts/ Helper scripts for the project
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### How it works
|
|
165
|
+
|
|
166
|
+
- The app is a few hundred lines of vanilla JavaScript (ESM) in `mevebu/app/mevebu.js`, plus a small shared helper set in `mevebu/libs/js/core.js`.
|
|
167
|
+
- The registry in `mevebu/libs/js/registry.js` is the single source of truth for all tools.
|
|
168
|
+
- The styling is Tailwind v4, built from one source file. The built stylesheet is committed, so the shipped folder stays plain static files.
|
|
169
|
+
- The design system (type scale, layout, color, and motion) is documented in `AGENTS.md` and `DESIGN.md`.
|
|
170
|
+
|
|
171
|
+
### Add a new tool
|
|
172
|
+
|
|
173
|
+
1. Create one file in `mevebu/libs/js/tools/`.
|
|
174
|
+
2. Export a `mount(slot)` function. Optionally export `unmount()` to clean up timers, cameras, and observers.
|
|
175
|
+
3. Add one entry to `TOOLS` in `mevebu/libs/js/registry.js`.
|
|
176
|
+
|
|
177
|
+
That is all. The catalog, search, breadcrumbs, and category pages pick it up automatically.
|
|
178
|
+
|
|
179
|
+
## FAQ
|
|
180
|
+
|
|
181
|
+
**What is mevebu?**
|
|
182
|
+
mevebu is a free, open source collection of 187 browser based tools for developers, students, creators, and everyday use. Every tool runs locally in your browser.
|
|
183
|
+
|
|
184
|
+
**Is mevebu really free?**
|
|
185
|
+
Yes. It is MIT licensed, with no paid tier, no account, and no usage limits.
|
|
148
186
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
component layer and no `mvb-` class: every utility is written at the call
|
|
152
|
-
site, and the design tokens live in `mevebu/app/tailwind.src.css`.
|
|
187
|
+
**Does mevebu upload or store my data?**
|
|
188
|
+
No. Your input is processed in your browser tab and never sent to a server.
|
|
153
189
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
190
|
+
**Can I use mevebu offline?**
|
|
191
|
+
Yes. After you install it with npm, it runs on your own machine without needing the internet.
|
|
192
|
+
|
|
193
|
+
**Can I host mevebu on my own site?**
|
|
194
|
+
Yes. Copy the `mevebu/` folder to any static host. No server side setup is needed.
|
|
195
|
+
|
|
196
|
+
**How do I find a tool quickly?**
|
|
197
|
+
Press `Ctrl+K` and search by tool name, keyword, or what the tool does.
|
|
198
|
+
|
|
199
|
+
**Can I add my own tool?**
|
|
200
|
+
Yes. Add one file and one registry entry. See [Add a new tool](#add-a-new-tool).
|
|
157
201
|
|
|
158
202
|
## Report a problem
|
|
159
203
|
|
|
160
|
-
Every tool page has a small
|
|
161
|
-
the tool's actions. It opens a GitHub issue with the tool name, the page URL
|
|
162
|
-
and the mevebu version already filled in, so all you have to do is describe
|
|
163
|
-
what happened and what you expected.
|
|
204
|
+
Every tool page has a small **Report a problem** link at the bottom. It opens a GitHub issue with the tool name, the page URL, and the mevebu version already filled in. You only need to describe what happened and what you expected.
|
|
164
205
|
|
|
165
|
-
|
|
206
|
+
You can also [open an issue](https://github.com/mevebu/mevebu/issues) directly, or send a pull request.
|
|
207
|
+
|
|
208
|
+
## Support and follow
|
|
209
|
+
|
|
210
|
+
If a tool here saved you time, you can help keep the next one coming:
|
|
166
211
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
212
|
+
[](https://buymeacoffee.com/fastro)
|
|
213
|
+
|
|
214
|
+
Star the repo if you like it, and follow mevebu for updates:
|
|
215
|
+
|
|
216
|
+
[GitHub](https://github.com/mevebu) · [TikTok](https://www.tiktok.com/@mevebu01) · [Instagram](https://www.instagram.com/mevebu01) · [Facebook](https://www.facebook.com/mevebu) · [YouTube](https://www.youtube.com/@mevebu) · [Threads](https://www.threads.net/@mevebu01)
|
|
170
217
|
|
|
171
218
|
## Links
|
|
172
219
|
|
|
173
220
|
- Repository: <https://github.com/mevebu/mevebu>
|
|
174
|
-
- npm: <https://www.npmjs.com/package/mevebu>
|
|
175
|
-
-
|
|
221
|
+
- npm package: <https://www.npmjs.com/package/mevebu>
|
|
222
|
+
- Issues: <https://github.com/mevebu/mevebu/issues>
|
|
223
|
+
|
|
224
|
+
## License
|
|
225
|
+
|
|
226
|
+
[MIT](./LICENSE). The whole list, the whole source, the whole thing is right here in the repository.
|
package/mevebu/app/mevebu.js
CHANGED
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
$, $$, el, icon, getFavorites, isFavorite, toggleFavorite, setTheme,
|
|
8
8
|
modal, modalHead, button, copyButton, openPalette, shuffle, toolcard, blank,
|
|
9
9
|
VERSION, PACKAGE_NAME, checkForUpdate, updateCommand, compareVersions, releaseUrl,
|
|
10
|
+
textInput, textArea, panel,
|
|
10
11
|
} from "../libs/js/core.js";
|
|
11
12
|
|
|
12
13
|
const DONATE_URL = "https://buymeacoffee.com/fastro";
|
|
@@ -754,28 +755,115 @@ function moreFromMev(tool) {
|
|
|
754
755
|
);
|
|
755
756
|
}
|
|
756
757
|
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
""
|
|
765
|
-
|
|
766
|
-
""
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
""
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
758
|
+
// What the browser tells us about itself, without asking the user to retype it.
|
|
759
|
+
// Every field can come back empty (a hardened browser, a private mode), so the
|
|
760
|
+
// form still works when it does.
|
|
761
|
+
function browserFacts() {
|
|
762
|
+
const ua = navigator.userAgent;
|
|
763
|
+
const browser = /Edg\//.test(ua) ? "Edge"
|
|
764
|
+
: /OPR\//.test(ua) ? "Opera"
|
|
765
|
+
: /Firefox\//.test(ua) ? "Firefox"
|
|
766
|
+
: /Chrome\//.test(ua) ? "Chrome"
|
|
767
|
+
: /Safari\//.test(ua) ? "Safari"
|
|
768
|
+
: "Unknown";
|
|
769
|
+
const version = (ua.match(new RegExp(browser + "\\/([\\d.]+)")) ?? [])[1] ?? "";
|
|
770
|
+
const platform = navigator.userAgentData?.platform
|
|
771
|
+
?? (/Windows/.test(ua) ? "Windows" : /Mac OS X/.test(ua) ? "macOS"
|
|
772
|
+
: /Android/.test(ua) ? "Android" : /iPhone|iPad/.test(ua) ? "iOS"
|
|
773
|
+
: /Linux/.test(ua) ? "Linux" : "");
|
|
774
|
+
const screen = `${window.screen.width}x${window.screen.height} @${window.devicePixelRatio}x`;
|
|
775
|
+
return { browser: `${browser} ${version}`.trim(), platform, screen };
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
function openReport(tool) {
|
|
779
|
+
const facts = browserFacts();
|
|
780
|
+
const doing = textArea({ rows: 3, placeholder: "I was building a daily expression for a backup job." });
|
|
781
|
+
const happened = textArea({ rows: 3, placeholder: "The preview stayed empty when I typed 0 3." });
|
|
782
|
+
const expected = textArea({ rows: 3, placeholder: "I expected it to read \"03:00 every day\"." });
|
|
783
|
+
const browserField = textInput({ value: facts.browser });
|
|
784
|
+
const platformField = textInput({ value: [facts.platform, facts.screen].filter(Boolean).join(" · ") });
|
|
785
|
+
let opened = false;
|
|
786
|
+
|
|
787
|
+
const submit = button("Open GitHub issue", { icon: "external-link", kind: "fill" });
|
|
788
|
+
// The actions row renders outside the form, so the button names it explicitly.
|
|
789
|
+
submit.type = "submit";
|
|
790
|
+
submit.setAttribute("form", "report-form");
|
|
791
|
+
submit.disabled = true;
|
|
792
|
+
submit.setAttribute("aria-disabled", "true");
|
|
793
|
+
const validate = () => {
|
|
794
|
+
const ready = happened.value.trim().length > 0 && doing.value.trim().length > 0;
|
|
795
|
+
submit.disabled = !ready;
|
|
796
|
+
if (ready) submit.removeAttribute("aria-disabled");
|
|
797
|
+
else submit.setAttribute("aria-disabled", "true");
|
|
798
|
+
};
|
|
799
|
+
for (const area of [doing, happened]) area.addEventListener("input", validate);
|
|
800
|
+
|
|
801
|
+
const form = el(
|
|
802
|
+
"form",
|
|
803
|
+
{
|
|
804
|
+
id: "report-form",
|
|
805
|
+
class: "grid gap-3.5",
|
|
806
|
+
onsubmit: (event) => {
|
|
807
|
+
event.preventDefault();
|
|
808
|
+
if (opened || submit.disabled) return;
|
|
809
|
+
opened = true;
|
|
810
|
+
const body = [
|
|
811
|
+
"### What I was doing",
|
|
812
|
+
doing.value.trim() || "_not given_",
|
|
813
|
+
"",
|
|
814
|
+
"### What happened",
|
|
815
|
+
happened.value.trim() || "_not given_",
|
|
816
|
+
"",
|
|
817
|
+
"### What I expected",
|
|
818
|
+
expected.value.trim() || "_not given_",
|
|
819
|
+
"",
|
|
820
|
+
"### Where",
|
|
821
|
+
`- Tool: ${tool.name} (\`${tool.id}\`)`,
|
|
822
|
+
`- Page: #/${tool.category}/${tool.id}`,
|
|
823
|
+
`- mevebu: ${VERSION}`,
|
|
824
|
+
"",
|
|
825
|
+
"### Browser",
|
|
826
|
+
`- ${browserField.value || "unknown"}`,
|
|
827
|
+
`- ${platformField.value || "unknown"}`,
|
|
828
|
+
].join("\n");
|
|
829
|
+
const title = `Bug in ${tool.name}`;
|
|
830
|
+
const href = `https://github.com/mevebu/mevebu/issues/new?title=${encodeURIComponent(title)}&body=${encodeURIComponent(body)}`;
|
|
831
|
+
window.open(href, "_blank", "noopener");
|
|
832
|
+
},
|
|
833
|
+
},
|
|
834
|
+
panel("What were you doing?", doing),
|
|
835
|
+
panel("What happened?", happened),
|
|
836
|
+
panel("What did you expect?", expected, "Optional"),
|
|
837
|
+
el(
|
|
838
|
+
"div",
|
|
839
|
+
{ class: "grid gap-3 rounded-r2 border border-orbit bg-deck-2 p-3.5" },
|
|
840
|
+
el("p", { class: "m-0 text-2xs text-ink-3" },
|
|
841
|
+
"Already filled in from this tab. Edit it if something is off."),
|
|
842
|
+
panel("Browser", browserField),
|
|
843
|
+
panel("Screen", platformField),
|
|
844
|
+
),
|
|
845
|
+
submit
|
|
846
|
+
);
|
|
847
|
+
|
|
848
|
+
modal({
|
|
849
|
+
label: `Report a problem with ${tool.name}`,
|
|
850
|
+
panelClass: "m-auto w-[min(560px,100%)] p-[clamp(22px,3vw,28px)] max-h-[calc(100dvh-40px)] overflow-y-auto",
|
|
851
|
+
body: [
|
|
852
|
+
modalHead("flag", `Report a problem with ${tool.name}`),
|
|
853
|
+
el("p", { class: "m-0 text-sm text-ink-2" },
|
|
854
|
+
"Tell us what went wrong and the issue opens on GitHub with this page and browser already filled in."),
|
|
855
|
+
form,
|
|
856
|
+
],
|
|
857
|
+
actions: [submit],
|
|
858
|
+
});
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
function reportButton(tool) {
|
|
862
|
+
return button("Report a problem", {
|
|
863
|
+
icon: "flag",
|
|
864
|
+
class: "mt-4",
|
|
865
|
+
onclick: () => openReport(tool),
|
|
866
|
+
});
|
|
779
867
|
}
|
|
780
868
|
|
|
781
869
|
async function toolPage(tool, category) {
|
|
@@ -788,7 +876,7 @@ async function toolPage(tool, category) {
|
|
|
788
876
|
{ class: PAGE_NARROW },
|
|
789
877
|
benchHead(tool, category),
|
|
790
878
|
slot,
|
|
791
|
-
el("div", { class: "flex flex-col items-
|
|
879
|
+
el("div", { class: "flex flex-col items-start" }, reportButton(tool)),
|
|
792
880
|
more
|
|
793
881
|
);
|
|
794
882
|
|