@caperjs/core 0.7.2 → 0.7.3
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/cli/native.mjs +21 -4
- package/cli/native.test.mjs +35 -3
- package/extras/llms.txt +10 -1
- package/lib/caper.mjs +86 -86
- package/lib/caper.mjs.map +1 -1
- package/lib/{const-Cj14a5U2.js → const-BClauBNo.js} +103 -95
- package/lib/{const-Cj14a5U2.js.map → const-BClauBNo.js.map} +1 -1
- package/lib/ui/UICanvas.d.ts +10 -2
- package/lib/ui/UICanvas.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/ui/UICanvas.test.ts +23 -1
- package/src/ui/UICanvas.ts +22 -3
- package/src/version.ts +1 -1
package/cli/native.mjs
CHANGED
|
@@ -18,6 +18,16 @@ const IDENTIFIER_RE = /^[a-z][a-z0-9]*(\.[a-z][a-z0-9-]*)+$/;
|
|
|
18
18
|
const PLACEHOLDER_IDENTIFIER = 'com.tauri.dev';
|
|
19
19
|
const DEFAULT_IDENTIFIER_PREFIX = 'dev.caper.';
|
|
20
20
|
|
|
21
|
+
/** A window/app title from a package name: strip an npm scope, split on `-`/`_`/`.`, capitalize each word. */
|
|
22
|
+
export function displayTitle(packageName) {
|
|
23
|
+
return String(packageName ?? '')
|
|
24
|
+
.replace(/^@[^/]+\//, '')
|
|
25
|
+
.split(/[-_.\s]+/)
|
|
26
|
+
.filter(Boolean)
|
|
27
|
+
.map((word) => word[0].toUpperCase() + word.slice(1))
|
|
28
|
+
.join(' ');
|
|
29
|
+
}
|
|
30
|
+
|
|
21
31
|
/** Strip an npm scope, lowercase, collapse non `[a-z0-9]` runs to `-`, trim `-`. */
|
|
22
32
|
export function appSlug(packageName) {
|
|
23
33
|
return String(packageName ?? '')
|
|
@@ -219,7 +229,7 @@ export async function initNative(cwd, opts = {}, { run = defaultRun } = {}) {
|
|
|
219
229
|
// vars can instead reflect an unrelated ancestor process (e.g. a monorepo
|
|
220
230
|
// task runner). Read the name straight from the package.json we already have.
|
|
221
231
|
const name = pkg.name ?? 'app';
|
|
222
|
-
const title = opts.title ?? name;
|
|
232
|
+
const title = opts.title ?? displayTitle(name);
|
|
223
233
|
const slug = appSlug(pkg.name ?? name);
|
|
224
234
|
|
|
225
235
|
const identifier = opts.identifier ?? defaultIdentifier(slug);
|
|
@@ -244,7 +254,7 @@ export async function initNative(cwd, opts = {}, { run = defaultRun } = {}) {
|
|
|
244
254
|
'init',
|
|
245
255
|
'--ci',
|
|
246
256
|
'--app-name',
|
|
247
|
-
|
|
257
|
+
title,
|
|
248
258
|
'--window-title',
|
|
249
259
|
title,
|
|
250
260
|
'--frontend-dist',
|
|
@@ -262,7 +272,10 @@ export async function initNative(cwd, opts = {}, { run = defaultRun } = {}) {
|
|
|
262
272
|
const tauriConf = JSON.parse(fs.readFileSync(tauriConfPath, 'utf-8'));
|
|
263
273
|
writeJson(tauriConfPath, patchTauriConfig(tauriConf, { identifier, title }), 2);
|
|
264
274
|
|
|
265
|
-
|
|
275
|
+
// Re-read: the package manager rewrote package.json when it added @tauri-apps/cli,
|
|
276
|
+
// and patching the copy read above would silently drop that devDependency.
|
|
277
|
+
const freshPkgRaw = fs.readFileSync(pkgPath, 'utf-8');
|
|
278
|
+
writeJson(pkgPath, patchPackageScripts(JSON.parse(freshPkgRaw)), detectIndent(freshPkgRaw));
|
|
266
279
|
|
|
267
280
|
if (opts.icon) {
|
|
268
281
|
run(EXEC_RUNNER[pm], ['tauri', 'icon', opts.icon], { cwd });
|
|
@@ -666,7 +679,7 @@ export async function androidNative(
|
|
|
666
679
|
}
|
|
667
680
|
|
|
668
681
|
function printUsage() {
|
|
669
|
-
console.error(red('Usage: caper native init [--identifier <id>] [--port <n>] [--icon <png>]'));
|
|
682
|
+
console.error(red('Usage: caper native init [--title <name>] [--identifier <id>] [--port <n>] [--icon <png>]'));
|
|
670
683
|
console.error(red(' caper native plugin'));
|
|
671
684
|
console.error(red(' caper native android'));
|
|
672
685
|
}
|
|
@@ -687,6 +700,10 @@ function parseInitArgs(args) {
|
|
|
687
700
|
const next = args[++i];
|
|
688
701
|
if (!next) throw new Error('Missing value for --icon');
|
|
689
702
|
opts.icon = next;
|
|
703
|
+
} else if (arg === '--title') {
|
|
704
|
+
const next = args[++i];
|
|
705
|
+
if (!next) throw new Error('Missing value for --title');
|
|
706
|
+
opts.title = next;
|
|
690
707
|
} else {
|
|
691
708
|
throw new Error(`Unknown option: ${arg}`);
|
|
692
709
|
}
|
package/cli/native.test.mjs
CHANGED
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
commandsFor,
|
|
15
15
|
defaultIdentifier,
|
|
16
16
|
defaultPort,
|
|
17
|
+
displayTitle,
|
|
17
18
|
findMainActivity,
|
|
18
19
|
initNative,
|
|
19
20
|
isValidIdentifier,
|
|
@@ -46,6 +47,14 @@ function makeTempDir() {
|
|
|
46
47
|
return tempDir;
|
|
47
48
|
}
|
|
48
49
|
|
|
50
|
+
describe('displayTitle', () => {
|
|
51
|
+
it('title-cases a package name into a window title', () => {
|
|
52
|
+
expect(displayTitle('rhodora')).toBe('Rhodora');
|
|
53
|
+
expect(displayTitle('my-game')).toBe('My Game');
|
|
54
|
+
expect(displayTitle('@studio/space_rocks')).toBe('Space Rocks');
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
|
|
49
58
|
describe('appSlug', () => {
|
|
50
59
|
it('strips a scope, lowercases, and collapses non-alnum runs to a hyphen', () => {
|
|
51
60
|
expect(appSlug('@acme/My Game')).toBe('my-game');
|
|
@@ -315,6 +324,29 @@ describe('initNative', () => {
|
|
|
315
324
|
};
|
|
316
325
|
}
|
|
317
326
|
|
|
327
|
+
it('keeps the @tauri-apps/cli devDependency the package manager just added', async () => {
|
|
328
|
+
const dir = makeTempDir();
|
|
329
|
+
scaffoldApp(dir);
|
|
330
|
+
const calls = [];
|
|
331
|
+
const tauriRun = stubbedRun(calls);
|
|
332
|
+
// Like a real `pnpm add -D`, write the devDependency into package.json.
|
|
333
|
+
const run = (cmd, args, opts) => {
|
|
334
|
+
if (args[0] === 'add') {
|
|
335
|
+
const pkgPath = path.join(opts.cwd, 'package.json');
|
|
336
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
337
|
+
pkg.devDependencies = { ...pkg.devDependencies, '@tauri-apps/cli': '^2.12.1' };
|
|
338
|
+
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n', 'utf-8');
|
|
339
|
+
}
|
|
340
|
+
return tauriRun(cmd, args, opts);
|
|
341
|
+
};
|
|
342
|
+
|
|
343
|
+
await initNative(dir, {}, { run });
|
|
344
|
+
|
|
345
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(dir, 'package.json'), 'utf-8'));
|
|
346
|
+
expect(pkg.devDependencies['@tauri-apps/cli']).toBe('^2.12.1');
|
|
347
|
+
expect(pkg.scripts['native:build']).toBe('tauri build');
|
|
348
|
+
});
|
|
349
|
+
|
|
318
350
|
it('does nothing and makes zero run calls when src-tauri already exists', async () => {
|
|
319
351
|
const dir = makeTempDir();
|
|
320
352
|
scaffoldApp(dir);
|
|
@@ -360,9 +392,9 @@ describe('initNative', () => {
|
|
|
360
392
|
'init',
|
|
361
393
|
'--ci',
|
|
362
394
|
'--app-name',
|
|
363
|
-
'
|
|
395
|
+
'My Game',
|
|
364
396
|
'--window-title',
|
|
365
|
-
'
|
|
397
|
+
'My Game',
|
|
366
398
|
'--frontend-dist',
|
|
367
399
|
'../dist',
|
|
368
400
|
'--dev-url',
|
|
@@ -375,7 +407,7 @@ describe('initNative', () => {
|
|
|
375
407
|
|
|
376
408
|
const conf = JSON.parse(fs.readFileSync(path.join(dir, 'src-tauri/tauri.conf.json'), 'utf-8'));
|
|
377
409
|
expect(conf.identifier).toBe('dev.caper.mygame');
|
|
378
|
-
expect(conf.app.windows[0]).toMatchObject({ title: '
|
|
410
|
+
expect(conf.app.windows[0]).toMatchObject({ title: 'My Game', width: 1280, height: 720 });
|
|
379
411
|
expect(conf.app.security.csp).toBeNull();
|
|
380
412
|
expect(conf.bundle).toEqual({ active: true, targets: ['app'] });
|
|
381
413
|
|
package/extras/llms.txt
CHANGED
|
@@ -219,7 +219,7 @@ subcommands run from the app root.
|
|
|
219
219
|
| `caper doctor [--offline] [--json]` | One-screen health check: installed vs latest caper, npm vs linked engine (and whether the linked build is stale), generated types present/fresh, asset manifest, agent pointers, peer deps, caches. Exit 1 on any ✗. |
|
|
220
220
|
| `caper agent init [--dir <skillsDir>]` | Install the shipped `caper` agent skill (default `.claude/skills/caper/SKILL.md`) and upsert a pointer block into `AGENTS.md`/`CLAUDE.md`. Re-run after upgrading caper. |
|
|
221
221
|
| `caper agent probe <url> [--action n[=json]]… [--until "<js predicate>"] [--wait ms] [--screenshot p] [--headed] [--json]` | Drive a **running** app headlessly through the automation bridge (§17) in a Chromium you own: boots, sends actions, waits on state, returns context/state/log/errors (+ screenshot). Needs `playwright` in the app's devDependencies. |
|
|
222
|
-
| `caper native init [--identifier <id>] [--port <n>] [--icon <png>]` | One-shot Tauri v2 scaffolding: adds `@tauri-apps/cli`, runs `tauri init --ci`, pins a `dev.caper.*`-style identifier + a stable non-3000 dev port, adds `native:dev`/`native:build` scripts. No-ops with "already initialized" if `src-tauri/` exists. |
|
|
222
|
+
| `caper native init [--title <name>] [--identifier <id>] [--port <n>] [--icon <png>]` | One-shot Tauri v2 scaffolding: adds `@tauri-apps/cli`, runs `tauri init --ci`, names the app and window after the package (title-cased: `my-game` → "My Game"; `--title` overrides), pins a `dev.caper.*`-style identifier + a stable non-3000 dev port, adds `native:dev`/`native:build` scripts. No-ops with "already initialized" if `src-tauri/` exists. |
|
|
223
223
|
| `caper native plugin` | Wires an already-`native init`'d app up for `@caperjs/plugin-tauri`: adds its JS deps, runs `tauri add store`, and patches the window permissions it needs into `capabilities/default.json`. Fails with "run `caper native init` first" if `src-tauri/` is missing; idempotent otherwise. |
|
|
224
224
|
| `caper native android` | Sets an already-`native init`'d app up for Android: finds the SDK/NDK/JDK/rustup, adds the four Android Rust targets, runs `tauri android init --ci`, adds 16 KB page alignment to `build.rs`, hides the system bars in `MainActivity.kt`, adds `native:android:dev`/`native:android:build` scripts. Idempotent; warns instead of overwriting files you changed. |
|
|
225
225
|
| `caper update` | Update Caper to latest. |
|
|
@@ -834,6 +834,15 @@ then push toasts to it. Also available as `app.popups.toast(...)`.
|
|
|
834
834
|
|
|
835
835
|
A FlexContainer preset for app-size-bound HUDs. Use as the root of in-game UI.
|
|
836
836
|
|
|
837
|
+
It pads by the device safe-area insets (notch, camera hole, gesture bar) by
|
|
838
|
+
default. `useSafeArea: false` turns that off; `{ top: false }` turns off one
|
|
839
|
+
edge, e.g. to let corner buttons sit in a punch-hole phone's camera strip:
|
|
840
|
+
|
|
841
|
+
```ts
|
|
842
|
+
import { isAndroid, isTauri } from '@caperjs/core';
|
|
843
|
+
const hud = this.add.uiCanvas({ useAppSize: true, useSafeArea: isTauri && isAndroid ? { top: false } : true });
|
|
844
|
+
```
|
|
845
|
+
|
|
837
846
|
### 7.6 `Joystick` — virtual stick
|
|
838
847
|
|
|
839
848
|
For touch input. Wires into the `controls.touch.joystick` bindings set via
|