mevebu 1.9.0 → 1.11.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 +9 -8
- package/mevebu/app/mevebu.js +131 -4
- package/mevebu/app/tailwind.css +221 -0
- package/mevebu/libs/js/core.js +1 -1
- package/mevebu/libs/js/files.js +125 -0
- package/mevebu/libs/js/icons.js +3 -2
- package/mevebu/libs/js/pdf-engine.js +67 -0
- package/mevebu/libs/js/registry.js +190 -9
- package/mevebu/libs/js/social-icons.js +32 -0
- package/mevebu/libs/js/tools/audio-converter.js +228 -0
- package/mevebu/libs/js/tools/image-to-pdf.js +251 -0
- package/mevebu/libs/js/tools/pdf-merge.js +158 -0
- package/mevebu/libs/js/tools/pdf-organizer.js +215 -0
- package/mevebu/libs/js/tools/pdf-split.js +198 -0
- package/mevebu/libs/js/tools/pdf-to-image.js +190 -0
- package/mevebu/libs/js/tools/pdf-to-text.js +172 -0
- package/mevebu/libs/js/tools/scientific-calculator.js +366 -189
- package/mevebu/libs/js/tools/subtitle-formatter.js +1 -1
- package/mevebu/libs/js/tools/svg-to-png.js +207 -0
- package/mevebu/libs/js/tools/text-to-pdf.js +182 -0
- package/mevebu/libs/js/tools/video-converter.js +316 -0
- package/mevebu/libs/js/vendor/mathjs.LICENSE.txt +34 -0
- package/mevebu/libs/js/vendor/mathjs.min.js +3 -0
- package/mevebu/libs/js/vendor/pdf-lib.LICENSE.md +21 -0
- package/mevebu/libs/js/vendor/pdf-lib.min.js +16 -0
- package/mevebu/libs/js/vendor/pdf.min.mjs +21 -0
- package/mevebu/libs/js/vendor/pdf.worker.min.mjs +21 -0
- package/mevebu/libs/js/vendor/pdfjs.LICENSE +177 -0
- package/package.json +7 -2
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# mevebu
|
|
4
4
|
|
|
5
|
-
**
|
|
5
|
+
**198 free browser tools, one page each. No sign up. No uploads. Everything runs in your tab.**
|
|
6
6
|
|
|
7
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.
|
|
8
8
|
|
|
@@ -10,7 +10,7 @@ A private toolbox for the small jobs that do not deserve a whole app: format JSO
|
|
|
10
10
|
[](https://www.npmjs.com/package/mevebu)
|
|
11
11
|
[](./LICENSE)
|
|
12
12
|
[](https://github.com/mevebu/mevebu/stargazers)
|
|
13
|
-

|
|
14
14
|

|
|
15
15
|
|
|
16
16
|
[Quick start](#quick-start) · [What's inside](#whats-inside) · [Privacy](#privacy-by-design) · [Host it yourself](#host-it-yourself) · [Development](#development) · [FAQ](#faq)
|
|
@@ -23,7 +23,7 @@ A private toolbox for the small jobs that do not deserve a whole app: format JSO
|
|
|
23
23
|
|
|
24
24
|
## What is mevebu?
|
|
25
25
|
|
|
26
|
-
mevebu is a collection of **
|
|
26
|
+
mevebu is a collection of **198 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
27
|
|
|
28
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
29
|
|
|
@@ -65,14 +65,14 @@ mevebu tries port `5555` first, then `5678`, then `5432`, and finally any free p
|
|
|
65
65
|
|
|
66
66
|
## What's inside
|
|
67
67
|
|
|
68
|
-
mevebu has **
|
|
68
|
+
mevebu has **198 tools in 20 categories**. Here is the full breakdown:
|
|
69
69
|
|
|
70
70
|
| Category | Tools |
|
|
71
71
|
| ------------------ | ----: |
|
|
72
72
|
| Random | 3 |
|
|
73
73
|
| Passwords and keys | 10 |
|
|
74
74
|
| Developer | 21 |
|
|
75
|
-
| Convert |
|
|
75
|
+
| Convert | 15 |
|
|
76
76
|
| Text and data | 14 |
|
|
77
77
|
| Daily use | 8 |
|
|
78
78
|
| Math | 17 |
|
|
@@ -89,7 +89,7 @@ mevebu has **188 tools in 20 categories**. Here is the full breakdown:
|
|
|
89
89
|
| GitHub | 8 |
|
|
90
90
|
| Units | 8 |
|
|
91
91
|
| QR codes | 2 |
|
|
92
|
-
| **Total** | **
|
|
92
|
+
| **Total** | **198** |
|
|
93
93
|
|
|
94
94
|
The counts come straight from the tool registry, so this table and the app never drift apart.
|
|
95
95
|
|
|
@@ -109,7 +109,7 @@ Browse everything from the home page or by category, or just press `Ctrl+K` and
|
|
|
109
109
|
|
|
110
110
|
## Privacy by design
|
|
111
111
|
|
|
112
|
-
mevebu is built so that your data has nowhere to go. Every tool is a static HTML file
|
|
112
|
+
mevebu is built so that your data has nowhere to go. Every tool is a static HTML file and a small JavaScript module. Icons are Lucide, brand marks are Simple Icons, and the libraries that do real work (mathjs, pdf-lib, pdf.js, jsQR) are vendored into the folder rather than fetched from a CDN. There is no server side code, no analytics, and no API key.
|
|
113
113
|
|
|
114
114
|
When you paste a password, a token, or a CSV into a tool:
|
|
115
115
|
|
|
@@ -148,6 +148,7 @@ cd mevebu
|
|
|
148
148
|
npm install
|
|
149
149
|
npm run css # build the stylesheet from tailwind.src.css
|
|
150
150
|
npm run icons # regenerate the vendored Lucide icon set
|
|
151
|
+
npm run social # regenerate the vendored Simple Icons brand marks
|
|
151
152
|
npm start # serve the static folder on http://localhost:5555
|
|
152
153
|
```
|
|
153
154
|
|
|
@@ -179,7 +180,7 @@ That is all. The catalog, search, breadcrumbs, and category pages pick it up aut
|
|
|
179
180
|
## FAQ
|
|
180
181
|
|
|
181
182
|
**What is mevebu?**
|
|
182
|
-
mevebu is a free, open source collection of
|
|
183
|
+
mevebu is a free, open source collection of 198 browser based tools for developers, students, creators, and everyday use. Every tool runs locally in your browser.
|
|
183
184
|
|
|
184
185
|
**Is mevebu really free?**
|
|
185
186
|
Yes. It is MIT licensed, with no paid tier, no account, and no usage limits.
|
package/mevebu/app/mevebu.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// wiring, the home page, the tool index, and the bench a tool mounts into.
|
|
3
3
|
|
|
4
4
|
import { CATEGORIES, TOOLS, getTool, getCategory, toolsInCategory, toolHref } from "../libs/js/registry.js";
|
|
5
|
+
import { socialIcon } from "../libs/js/social-icons.js";
|
|
5
6
|
import { route, start, match, currentPath, go } from "../libs/js/router.js";
|
|
6
7
|
import {
|
|
7
8
|
$, $$, el, icon, getFavorites, isFavorite, toggleFavorite, setTheme,
|
|
@@ -11,6 +12,28 @@ import {
|
|
|
11
12
|
} from "../libs/js/core.js";
|
|
12
13
|
|
|
13
14
|
const REPO_URL = "https://github.com/mevebu/mevebu";
|
|
15
|
+
const WAITSEC_URL = "https://github.com/mevebu/waitsec";
|
|
16
|
+
const ORG_URL = "https://github.com/mevebu";
|
|
17
|
+
const CREATOR = {
|
|
18
|
+
name: "Ilyas Mukhlisin",
|
|
19
|
+
instagram: "https://www.instagram.com/ilyas.mukhlisin",
|
|
20
|
+
threads: "https://www.threads.com/@ilyas.mukhlisin",
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/* One list drives the footer modal and the about page, so an account is added
|
|
24
|
+
in one place and both surfaces follow. */
|
|
25
|
+
const MEVEBU_SOCIALS = [
|
|
26
|
+
{ name: "GitHub", handle: "@mevebu", href: ORG_URL, icon: "github" },
|
|
27
|
+
{ name: "Instagram", handle: "@mevebu01", href: "https://www.instagram.com/mevebu01", icon: "instagram" },
|
|
28
|
+
{ name: "Threads", handle: "@mevebu01", href: "https://www.threads.net/@mevebu01", icon: "threads" },
|
|
29
|
+
{ name: "TikTok", handle: "@mevebu01", href: "https://www.tiktok.com/@mevebu01", icon: "tiktok" },
|
|
30
|
+
{ name: "Facebook", handle: "mevebu", href: "https://www.facebook.com/mevebu", icon: "facebook" },
|
|
31
|
+
{ name: "YouTube", handle: "@mevebu", href: "https://www.youtube.com/@mevebu", icon: "youtube" },
|
|
32
|
+
];
|
|
33
|
+
const CREATOR_SOCIALS = [
|
|
34
|
+
{ name: "Instagram", handle: "@ilyas.mukhlisin", href: CREATOR.instagram, icon: "instagram" },
|
|
35
|
+
{ name: "Threads", handle: "@ilyas.mukhlisin", href: CREATOR.threads, icon: "threads" },
|
|
36
|
+
];
|
|
14
37
|
|
|
15
38
|
const NAV = [
|
|
16
39
|
{ path: "/", label: "Home" },
|
|
@@ -276,6 +299,46 @@ async function startVersionChip() {
|
|
|
276
299
|
});
|
|
277
300
|
}
|
|
278
301
|
|
|
302
|
+
function followRow(item) {
|
|
303
|
+
return el(
|
|
304
|
+
"a",
|
|
305
|
+
{
|
|
306
|
+
class:
|
|
307
|
+
"flex items-center gap-3 rounded-r1 border border-orbit bg-deck-2 p-2.5 text-ink no-underline transition-colors duration-150 hover:border-orbit-hard hover:bg-deck",
|
|
308
|
+
href: item.href,
|
|
309
|
+
target: "_blank",
|
|
310
|
+
rel: "noopener",
|
|
311
|
+
},
|
|
312
|
+
el("span", { class: "grid size-9 flex-none place-items-center rounded-lg bg-jade-soft text-jade" }, socialIcon(item.icon, "size-[18px]")),
|
|
313
|
+
el("span", { class: "grid min-w-0 gap-0.5" },
|
|
314
|
+
el("span", { class: "text-sm font-semibold" }, item.name),
|
|
315
|
+
el("span", { class: "truncate text-2xs text-ink-3" }, item.handle)),
|
|
316
|
+
icon("external-link", "ms-auto size-4 flex-none text-ink-3")
|
|
317
|
+
);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
function followGroup(title, items) {
|
|
321
|
+
return el(
|
|
322
|
+
"section",
|
|
323
|
+
{ class: "grid gap-2" },
|
|
324
|
+
el("h3", { class: "m-0 text-2xs font-bold tracking-[0.08em] text-ink-3 uppercase" }, title),
|
|
325
|
+
el("div", { class: "grid gap-1.5" }, ...items.map(followRow))
|
|
326
|
+
);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
function openFollow() {
|
|
330
|
+
modal({
|
|
331
|
+
label: "Follow mevebu",
|
|
332
|
+
body: [
|
|
333
|
+
modalHead("users-round", "Follow mevebu"),
|
|
334
|
+
el("p", { class: "m-0 text-sm leading-[1.6] text-ink-2" },
|
|
335
|
+
"Release notes, new tools, and the small updates in between. Pick a network."),
|
|
336
|
+
followGroup("mevebu", MEVEBU_SOCIALS),
|
|
337
|
+
followGroup(`${CREATOR.name}, creator`, CREATOR_SOCIALS),
|
|
338
|
+
],
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
|
|
279
342
|
function footer() {
|
|
280
343
|
// A finger needs 44px on a phone, so the whole list is a comfortable target
|
|
281
344
|
// there. The desktop row stays as it was, at text height.
|
|
@@ -322,6 +385,17 @@ function footer() {
|
|
|
322
385
|
"div",
|
|
323
386
|
{ class: "mt-[clamp(26px,4vw,44px)] flex flex-wrap items-center gap-x-5 gap-y-2 border-t border-orbit pt-5 text-2xs text-ink-3" },
|
|
324
387
|
el("p", { class: "m-0 flex items-center gap-2" }, "MIT licensed."),
|
|
388
|
+
el(
|
|
389
|
+
"button",
|
|
390
|
+
{
|
|
391
|
+
class:
|
|
392
|
+
"inline-flex min-h-7 cursor-pointer items-center gap-1.5 rounded-full border border-orbit bg-transparent px-2.5 py-[3px] font-sans text-2xs font-semibold text-ink-2 transition-colors duration-150 hover:border-jade hover:bg-jade-soft hover:text-jade max-[45rem]:min-h-11",
|
|
393
|
+
type: "button",
|
|
394
|
+
onclick: () => openFollow(),
|
|
395
|
+
},
|
|
396
|
+
icon("users-round", "size-3.5"),
|
|
397
|
+
"Follow us"
|
|
398
|
+
),
|
|
325
399
|
el(
|
|
326
400
|
"p",
|
|
327
401
|
{ class: "m-0 flex items-center gap-2" },
|
|
@@ -872,16 +946,69 @@ async function toolPage(tool, category) {
|
|
|
872
946
|
}
|
|
873
947
|
|
|
874
948
|
function aboutPage() {
|
|
949
|
+
const H1 = "m-0 text-[clamp(34px,6vw,52px)] font-bold tracking-[-0.03em]";
|
|
950
|
+
const SUB = "mt-3 mb-0 max-w-[64ch] text-pretty text-md leading-[1.6] text-ink-2";
|
|
875
951
|
const block = (title, ...nodes) =>
|
|
876
952
|
el("section", { class: ABOUT_BLOCK }, el("h2", { class: "text-lg font-bold tracking-[-0.01em]" }, title), ...nodes);
|
|
877
953
|
|
|
954
|
+
const stat = (value, label) =>
|
|
955
|
+
el("div", { class: "grid gap-0.5 rounded-r2 border border-orbit bg-deck-2 px-4 py-3" },
|
|
956
|
+
el("span", { class: "text-2xl font-bold tracking-[-0.02em] text-ink tabular-nums" }, value),
|
|
957
|
+
el("span", { class: "text-2xs font-semibold tracking-[0.06em] text-ink-3 uppercase" }, label));
|
|
958
|
+
|
|
959
|
+
const repoCard = (name, body, href) =>
|
|
960
|
+
el("a", {
|
|
961
|
+
class: "grid content-start gap-1.5 rounded-r2 border border-orbit bg-deck p-4 no-underline transition-colors duration-150 hover:border-orbit-hard hover:bg-deck-2",
|
|
962
|
+
href,
|
|
963
|
+
target: "_blank",
|
|
964
|
+
rel: "noopener",
|
|
965
|
+
},
|
|
966
|
+
el("span", { class: "flex items-center gap-2 text-md font-bold text-ink" },
|
|
967
|
+
icon("git-branch", "size-4 flex-none text-jade"), name),
|
|
968
|
+
el("span", { class: "text-sm leading-[1.55] text-ink-2" }, body),
|
|
969
|
+
el("span", { class: "mt-1 inline-flex items-center gap-1.5 font-mono text-2xs font-semibold text-jade" },
|
|
970
|
+
href.replace("https://", ""), icon("external-link", "size-3")));
|
|
971
|
+
|
|
972
|
+
const creatorLink = (item) =>
|
|
973
|
+
el("a", {
|
|
974
|
+
class: "inline-flex min-h-11 items-center gap-2 rounded-r1 border border-orbit bg-deck px-3 text-sm font-semibold text-ink no-underline transition-colors duration-150 hover:border-orbit-hard hover:bg-deck-2",
|
|
975
|
+
href: item.href,
|
|
976
|
+
target: "_blank",
|
|
977
|
+
rel: "noopener",
|
|
978
|
+
}, socialIcon(item.icon, "size-[17px] text-jade"), item.name);
|
|
979
|
+
|
|
878
980
|
document.title = "About · mevebu";
|
|
879
981
|
return el(
|
|
880
982
|
"div",
|
|
881
983
|
{ class: PAGE_NARROW },
|
|
882
|
-
el("
|
|
883
|
-
|
|
884
|
-
|
|
984
|
+
el("div", { class: "flex items-start gap-4" },
|
|
985
|
+
el("img", { class: "mt-1 block size-14 flex-none", src: "./assets/logo.png", alt: "", width: "56", height: "56" }),
|
|
986
|
+
el("div", { class: "min-w-0" },
|
|
987
|
+
el("h1", { class: H1 }, "About mevebu"),
|
|
988
|
+
el("p", { class: SUB },
|
|
989
|
+
"mevebu is a GitHub organization that builds small tools for the browser. Every tool runs on your device, with no account and nothing to upload."))),
|
|
990
|
+
|
|
991
|
+
el("div", { class: "mt-7 grid grid-cols-2 gap-2.5 sm:grid-cols-4" },
|
|
992
|
+
stat(String(TOOLS.length), "Tools"),
|
|
993
|
+
stat(String(CATEGORIES.length), "Categories"),
|
|
994
|
+
stat("2", "Repositories"),
|
|
995
|
+
stat("MIT", "License")),
|
|
996
|
+
|
|
997
|
+
block("The organization",
|
|
998
|
+
el("p", { class: "m-0 leading-[1.65] text-ink-2" },
|
|
999
|
+
"Everything sits under ", el("a", { class: TEXT_LINK, href: ORG_URL, target: "_blank", rel: "noopener" }, "github.com/mevebu"),
|
|
1000
|
+
". The organization holds two repositories: Mevebu, the toolbox you are using right now, and Waitsec, a set of guardrails for coding agents.")),
|
|
1001
|
+
|
|
1002
|
+
block("The repositories",
|
|
1003
|
+
el("div", { class: "grid gap-2.5 sm:grid-cols-2" },
|
|
1004
|
+
repoCard("Mevebu", `${TOOLS.length} browser tools in one static folder. No build step on your machine, no server behind it.`, REPO_URL),
|
|
1005
|
+
repoCard("Waitsec", "Guardrails for coding agents: stop first, think first, and write less code.", WAITSEC_URL))),
|
|
1006
|
+
|
|
1007
|
+
block("The creator",
|
|
1008
|
+
el("p", { class: "m-0 leading-[1.65] text-ink-2" },
|
|
1009
|
+
el("strong", { class: "font-semibold text-ink" }, CREATOR.name),
|
|
1010
|
+
" designs, builds and maintains both repositories. Follow the work on Instagram or Threads."),
|
|
1011
|
+
el("div", { class: "flex flex-wrap gap-2" }, ...CREATOR_SOCIALS.map(creatorLink))),
|
|
885
1012
|
|
|
886
1013
|
block("Running it",
|
|
887
1014
|
el("p", {}, "Install it once from npm. The command starts a local server and opens your browser at the address it prints."),
|
|
@@ -892,7 +1019,7 @@ function aboutPage() {
|
|
|
892
1019
|
el("p", {}, "Add one object to ", el("code", { class: CODE }, "mevebu/libs/js/registry.js"), " and one file in ", el("code", { class: CODE }, "mevebu/libs/js/tools/"), ". The home page, the index, the categories, search and the route all come from that entry.")),
|
|
893
1020
|
|
|
894
1021
|
block("Built with",
|
|
895
|
-
el("p", {}, "Hand written HTML, CSS and JavaScript, with Tailwind for the stylesheet.
|
|
1022
|
+
el("p", {}, "Hand written HTML, CSS and JavaScript, with Tailwind for the stylesheet. The scientific calculator runs on mathjs, icons are Lucide, brand marks are Simple Icons, and the QR decoder is jsQR."),
|
|
896
1023
|
el("p", {}, "Source and issues: ",
|
|
897
1024
|
el("a", { class: TEXT_LINK, href: REPO_URL, target: "_blank", rel: "noopener" }, "github.com/mevebu/mevebu")),
|
|
898
1025
|
el("p", {}, copyButton(() => location.href, "Copy this page link")))
|