murasaki 0.2.0 → 0.2.1

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.
Files changed (86) hide show
  1. package/bin/murasaki.js +8 -3
  2. package/dist/cli/colors.d.ts +13 -0
  3. package/dist/cli/colors.d.ts.map +1 -0
  4. package/dist/cli/colors.js +14 -0
  5. package/dist/cli/colors.js.map +1 -0
  6. package/dist/cli/log.d.ts +14 -0
  7. package/dist/cli/log.d.ts.map +1 -0
  8. package/dist/cli/log.js +25 -0
  9. package/dist/cli/log.js.map +1 -0
  10. package/dist/components/Link.d.ts +9 -0
  11. package/dist/components/Link.d.ts.map +1 -0
  12. package/dist/components/Link.js +15 -0
  13. package/dist/components/Link.js.map +1 -0
  14. package/dist/dev.d.ts +2 -0
  15. package/dist/dev.d.ts.map +1 -0
  16. package/dist/dev.js +41 -0
  17. package/dist/dev.js.map +1 -0
  18. package/dist/env.d.ts +15 -0
  19. package/dist/env.d.ts.map +1 -0
  20. package/dist/env.js +43 -0
  21. package/dist/env.js.map +1 -0
  22. package/dist/index.d.ts +18 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +7 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/jsx/index.d.ts +3 -0
  27. package/dist/jsx/index.d.ts.map +1 -0
  28. package/dist/jsx/index.js +3 -0
  29. package/dist/jsx/index.js.map +1 -0
  30. package/dist/jsx/jsx-dev-runtime.d.ts +2 -0
  31. package/dist/jsx/jsx-dev-runtime.d.ts.map +1 -0
  32. package/dist/jsx/jsx-dev-runtime.js +7 -0
  33. package/dist/jsx/jsx-dev-runtime.js.map +1 -0
  34. package/dist/jsx/jsx-runtime.d.ts +2 -0
  35. package/dist/jsx/jsx-runtime.d.ts.map +1 -0
  36. package/{src/jsx/jsx-runtime.ts → dist/jsx/jsx-runtime.js} +4 -3
  37. package/dist/jsx/jsx-runtime.js.map +1 -0
  38. package/dist/jsx/runtime.d.ts +24 -0
  39. package/dist/jsx/runtime.d.ts.map +1 -0
  40. package/dist/jsx/runtime.js +273 -0
  41. package/dist/jsx/runtime.js.map +1 -0
  42. package/dist/jsx/types.d.ts +30 -0
  43. package/dist/jsx/types.d.ts.map +1 -0
  44. package/dist/jsx/types.js +3 -0
  45. package/dist/jsx/types.js.map +1 -0
  46. package/dist/runtime/hmr.d.ts +2 -0
  47. package/dist/runtime/hmr.d.ts.map +1 -0
  48. package/dist/runtime/hmr.js +28 -0
  49. package/dist/runtime/hmr.js.map +1 -0
  50. package/dist/runtime/render.d.ts +3 -0
  51. package/dist/runtime/render.d.ts.map +1 -0
  52. package/dist/runtime/render.js +208 -0
  53. package/dist/runtime/render.js.map +1 -0
  54. package/dist/runtime/routes.d.ts +10 -0
  55. package/dist/runtime/routes.d.ts.map +1 -0
  56. package/dist/runtime/routes.js +65 -0
  57. package/dist/runtime/routes.js.map +1 -0
  58. package/dist/runtime/shortcuts.d.ts +8 -0
  59. package/dist/runtime/shortcuts.d.ts.map +1 -0
  60. package/dist/runtime/shortcuts.js +29 -0
  61. package/dist/runtime/shortcuts.js.map +1 -0
  62. package/dist/runtime/window.d.ts +10 -0
  63. package/dist/runtime/window.d.ts.map +1 -0
  64. package/dist/runtime/window.js +93 -0
  65. package/dist/runtime/window.js.map +1 -0
  66. package/dist/types.d.ts +17 -0
  67. package/dist/types.d.ts.map +1 -0
  68. package/dist/types.js +3 -0
  69. package/dist/types.js.map +1 -0
  70. package/package.json +12 -10
  71. package/src/cli/colors.ts +0 -16
  72. package/src/cli/log.ts +0 -42
  73. package/src/components/Link.tsx +0 -25
  74. package/src/dev.tsx +0 -60
  75. package/src/env.ts +0 -48
  76. package/src/index.ts +0 -24
  77. package/src/jsx/index.ts +0 -21
  78. package/src/jsx/jsx-dev-runtime.ts +0 -6
  79. package/src/jsx/runtime.ts +0 -298
  80. package/src/jsx/types.ts +0 -36
  81. package/src/runtime/hmr.ts +0 -26
  82. package/src/runtime/render.tsx +0 -225
  83. package/src/runtime/routes.ts +0 -73
  84. package/src/runtime/shortcuts.ts +0 -31
  85. package/src/runtime/window.ts +0 -94
  86. package/src/types.ts +0 -22
@@ -0,0 +1,65 @@
1
+ // File-based route discovery for src/app/.
2
+ //
3
+ // Conventions (subset of Next.js app router):
4
+ // src/app/page.tsx → "/"
5
+ // src/app/layout.tsx → root layout (wraps everything)
6
+ // src/app/about/page.tsx → "/about"
7
+ // src/app/about/layout.tsx → nested layout for /about and its children
8
+ // src/app/_foo/ → ignored (leading underscore = private)
9
+ //
10
+ // A page.tsx is required to register a route. A layout.tsx without a
11
+ // page.tsx in the same dir just contributes to children's layouts.
12
+ import { existsSync, readdirSync, statSync } from 'node:fs';
13
+ import { join } from 'node:path';
14
+ export function discoverRoutes(appDir) {
15
+ if (!existsSync(appDir))
16
+ return [];
17
+ const out = [];
18
+ walk(appDir, '', [], out);
19
+ // Stable sort so "/" comes first, then alphabetical
20
+ out.sort((a, b) => {
21
+ if (a.path === '/')
22
+ return -1;
23
+ if (b.path === '/')
24
+ return 1;
25
+ return a.path.localeCompare(b.path);
26
+ });
27
+ return out;
28
+ }
29
+ function walk(dir, routePath, layouts, out) {
30
+ let entries;
31
+ try {
32
+ entries = readdirSync(dir);
33
+ }
34
+ catch {
35
+ return;
36
+ }
37
+ const hasLayout = entries.includes('layout.tsx');
38
+ const hasPage = entries.includes('page.tsx');
39
+ // The current directory contributes its layout to itself and descendants.
40
+ const ownLayouts = hasLayout ? [...layouts, join(dir, 'layout.tsx')] : layouts;
41
+ if (hasPage) {
42
+ out.push({
43
+ path: routePath || '/',
44
+ pageFile: join(dir, 'page.tsx'),
45
+ layoutFiles: ownLayouts,
46
+ });
47
+ }
48
+ // Recurse into subdirectories (skip files, hidden, private "_*", node_modules).
49
+ for (const entry of entries) {
50
+ if (entry.startsWith('.') || entry.startsWith('_') || entry === 'node_modules')
51
+ continue;
52
+ const full = join(dir, entry);
53
+ let isDir = false;
54
+ try {
55
+ isDir = statSync(full).isDirectory();
56
+ }
57
+ catch {
58
+ continue;
59
+ }
60
+ if (!isDir)
61
+ continue;
62
+ walk(full, `${routePath}/${entry}`, ownLayouts, out);
63
+ }
64
+ }
65
+ //# sourceMappingURL=routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes.js","sourceRoot":"","sources":["../../src/runtime/routes.ts"],"names":[],"mappings":"AAAA,2CAA2C;AAC3C,EAAE;AACF,8CAA8C;AAC9C,oCAAoC;AACpC,+DAA+D;AAC/D,yCAAyC;AACzC,0EAA0E;AAC1E,uEAAuE;AACvE,EAAE;AACF,qEAAqE;AACrE,mEAAmE;AAEnE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAC3D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAWhC,MAAM,UAAU,cAAc,CAAC,MAAc;IAC3C,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC;QAAE,OAAO,EAAE,CAAA;IAClC,MAAM,GAAG,GAAY,EAAE,CAAA;IACvB,IAAI,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,CAAC,CAAA;IACzB,oDAAoD;IACpD,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QAChB,IAAI,CAAC,CAAC,IAAI,KAAK,GAAG;YAAE,OAAO,CAAC,CAAC,CAAA;QAC7B,IAAI,CAAC,CAAC,IAAI,KAAK,GAAG;YAAE,OAAO,CAAC,CAAA;QAC5B,OAAO,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;IACrC,CAAC,CAAC,CAAA;IACF,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,SAAS,IAAI,CAAC,GAAW,EAAE,SAAiB,EAAE,OAAiB,EAAE,GAAY;IAC3E,IAAI,OAAiB,CAAA;IACrB,IAAI,CAAC;QACH,OAAO,GAAG,WAAW,CAAC,GAAG,CAAC,CAAA;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,OAAM;IACR,CAAC;IAED,MAAM,SAAS,GAAG,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAA;IAChD,MAAM,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAA;IAE5C,0EAA0E;IAC1E,MAAM,UAAU,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAA;IAE9E,IAAI,OAAO,EAAE,CAAC;QACZ,GAAG,CAAC,IAAI,CAAC;YACP,IAAI,EAAE,SAAS,IAAI,GAAG;YACtB,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC;YAC/B,WAAW,EAAE,UAAU;SACxB,CAAC,CAAA;IACJ,CAAC;IAED,gFAAgF;IAChF,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,KAAK,cAAc;YAAE,SAAQ;QACxF,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;QAC7B,IAAI,KAAK,GAAG,KAAK,CAAA;QACjB,IAAI,CAAC;YACH,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAA;QACtC,CAAC;QAAC,MAAM,CAAC;YACP,SAAQ;QACV,CAAC;QACD,IAAI,CAAC,KAAK;YAAE,SAAQ;QACpB,IAAI,CAAC,IAAI,EAAE,GAAG,SAAS,IAAI,KAAK,EAAE,EAAE,UAAU,EAAE,GAAG,CAAC,CAAA;IACtD,CAAC;AACH,CAAC"}
@@ -0,0 +1,8 @@
1
+ export type ShortcutHandlers = {
2
+ onOpen: () => void;
3
+ onRestart: () => void;
4
+ onQuit: () => void;
5
+ };
6
+ export declare function setupShortcuts(handlers: ShortcutHandlers): void;
7
+ export declare function teardownStdin(): void;
8
+ //# sourceMappingURL=shortcuts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shortcuts.d.ts","sourceRoot":"","sources":["../../src/runtime/shortcuts.ts"],"names":[],"mappings":"AAOA,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,SAAS,EAAE,MAAM,IAAI,CAAA;IACrB,MAAM,EAAE,MAAM,IAAI,CAAA;CACnB,CAAA;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CAW/D;AAED,wBAAgB,aAAa,IAAI,IAAI,CAIpC"}
@@ -0,0 +1,29 @@
1
+ // Terminal keyboard shortcuts (raw mode stdin).
2
+ //
3
+ // o open the window
4
+ // r restart (close + open)
5
+ // q quit
6
+ // Ctrl+C quit
7
+ export function setupShortcuts(handlers) {
8
+ if (!process.stdin.isTTY)
9
+ return;
10
+ process.stdin.setRawMode(true);
11
+ process.stdin.resume();
12
+ process.stdin.setEncoding('utf8');
13
+ process.stdin.on('data', (key) => {
14
+ const k = key.toString();
15
+ if (k === 'o' || k === 'O')
16
+ handlers.onOpen();
17
+ else if (k === 'r' || k === 'R')
18
+ handlers.onRestart();
19
+ else if (k === 'q' || k === 'Q' || k === '\x03' /* Ctrl+C */)
20
+ handlers.onQuit();
21
+ });
22
+ }
23
+ export function teardownStdin() {
24
+ try {
25
+ process.stdin.setRawMode(false);
26
+ }
27
+ catch { }
28
+ }
29
+ //# sourceMappingURL=shortcuts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shortcuts.js","sourceRoot":"","sources":["../../src/runtime/shortcuts.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,EAAE;AACF,wBAAwB;AACxB,+BAA+B;AAC/B,aAAa;AACb,kBAAkB;AAQlB,MAAM,UAAU,cAAc,CAAC,QAA0B;IACvD,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK;QAAE,OAAM;IAChC,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,CAAA;IAC9B,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,CAAA;IACtB,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,CAAA;IACjC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE;QAC/B,MAAM,CAAC,GAAG,GAAG,CAAC,QAAQ,EAAE,CAAA;QACxB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,GAAG;YAAE,QAAQ,CAAC,MAAM,EAAE,CAAA;aACxC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,GAAG;YAAE,QAAQ,CAAC,SAAS,EAAE,CAAA;aAChD,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,MAAM,CAAC,YAAY;YAAE,QAAQ,CAAC,MAAM,EAAE,CAAA;IACjF,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,IAAI,CAAC;QACH,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,CAAA;IACjC,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;AACZ,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { Application } from '@webviewjs/webview';
2
+ import type { WindowConfig } from '../types.ts';
3
+ export declare const app: Application;
4
+ export declare function getConfig(): Readonly<WindowConfig>;
5
+ export declare function openWindow(): Promise<void>;
6
+ export declare function closeWindow(): void;
7
+ export declare function reloadWindow(triggerFile: string): Promise<void>;
8
+ export declare function runApp(): void;
9
+ export declare function exitApp(): void;
10
+ //# sourceMappingURL=window.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"window.d.ts","sourceRoot":"","sources":["../../src/runtime/window.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,WAAW,EAAe,MAAM,oBAAoB,CAAA;AAI7D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAS/C,eAAO,MAAM,GAAG,aAAqD,CAAA;AA+BrE,wBAAgB,SAAS,IAAI,QAAQ,CAAC,YAAY,CAAC,CAElD;AAED,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAahD;AAED,wBAAgB,WAAW,IAAI,IAAI,CAOlC;AAED,wBAAsB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CASrE;AAED,wBAAgB,MAAM,IAAI,IAAI,CAE7B;AAED,wBAAgB,OAAO,IAAI,IAAI,CAI9B"}
@@ -0,0 +1,93 @@
1
+ // Owns the Application + BrowserWindow lifecycle.
2
+ //
3
+ // The EventLoop is created exactly once (winit/tao limitation). ControlFlow.Wait
4
+ // keeps the loop alive even when no windows are open, so the user can press
5
+ // `o` in the terminal to re-open the window.
6
+ import { Application, ControlFlow } from '@webviewjs/webview';
7
+ import { printClosed, printError, printHint, printReloaded } from "../cli/log.js";
8
+ import { DEFAULT_WIN_SIZE, DEFAULT_WIN_TITLE, projectRoot } from "../env.js";
9
+ import { renderApp } from "./render.js";
10
+ const config = {
11
+ title: DEFAULT_WIN_TITLE,
12
+ width: DEFAULT_WIN_SIZE.width,
13
+ height: DEFAULT_WIN_SIZE.height,
14
+ };
15
+ export const app = new Application({ controlFlow: ControlFlow.Wait });
16
+ let win = null;
17
+ let webview = null;
18
+ app.onEvent((event) => {
19
+ const kind = event && (event.kind || event.event);
20
+ if (kind === 'window-close-requested') {
21
+ // Dispose so the OS close completes — without this the close button hangs.
22
+ if (win) {
23
+ try {
24
+ win.dispose();
25
+ }
26
+ catch { }
27
+ }
28
+ win = null;
29
+ webview = null;
30
+ printClosed();
31
+ }
32
+ });
33
+ function applyMetadata(metadata) {
34
+ if (!metadata)
35
+ return;
36
+ if (metadata.window?.title)
37
+ config.title = metadata.window.title;
38
+ else if (metadata.title)
39
+ config.title = metadata.title;
40
+ if (metadata.window?.width)
41
+ config.width = metadata.window.width;
42
+ if (metadata.window?.height)
43
+ config.height = metadata.window.height;
44
+ }
45
+ export function getConfig() {
46
+ return config;
47
+ }
48
+ export async function openWindow() {
49
+ if (win) {
50
+ printHint('Window is already open');
51
+ return;
52
+ }
53
+ const { html, metadata } = await renderApp();
54
+ applyMetadata(metadata);
55
+ win = app.createBrowserWindow({
56
+ title: config.title,
57
+ width: config.width,
58
+ height: config.height,
59
+ });
60
+ webview = win.createWebview({ html });
61
+ }
62
+ export function closeWindow() {
63
+ if (!win)
64
+ return;
65
+ try {
66
+ win.dispose();
67
+ }
68
+ catch { }
69
+ win = null;
70
+ webview = null;
71
+ }
72
+ export async function reloadWindow(triggerFile) {
73
+ if (!webview)
74
+ return;
75
+ try {
76
+ const { html } = await renderApp();
77
+ webview.loadHtml(html);
78
+ printReloaded(triggerFile.replace(projectRoot + '/', ''));
79
+ }
80
+ catch (e) {
81
+ printError(`Reload failed: ${e.message}`);
82
+ }
83
+ }
84
+ export function runApp() {
85
+ app.run();
86
+ }
87
+ export function exitApp() {
88
+ try {
89
+ app.exit();
90
+ }
91
+ catch { }
92
+ }
93
+ //# sourceMappingURL=window.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"window.js","sourceRoot":"","sources":["../../src/runtime/window.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { Metadata } from './index.ts';
2
+ import type { Component } from './jsx/types.ts';
3
+ export type AppComponent = Component;
4
+ export type LayoutModule = {
5
+ component: AppComponent;
6
+ metadata?: Metadata;
7
+ } | null;
8
+ export type WindowConfig = {
9
+ title: string;
10
+ width: number;
11
+ height: number;
12
+ };
13
+ export type RenderResult = {
14
+ html: string;
15
+ metadata?: Metadata;
16
+ };
17
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAC1C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAE/C,MAAM,MAAM,YAAY,GAAG,SAAS,CAAA;AAEpC,MAAM,MAAM,YAAY,GAAG;IACzB,SAAS,EAAE,YAAY,CAAA;IACvB,QAAQ,CAAC,EAAE,QAAQ,CAAA;CACpB,GAAG,IAAI,CAAA;AAER,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,CAAC,EAAE,QAAQ,CAAA;CACpB,CAAA"}
package/dist/types.js ADDED
@@ -0,0 +1,3 @@
1
+ // Internal shared types (the public Metadata type is re-exported from index.ts).
2
+ export {};
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,iFAAiF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "murasaki",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "The desktop framework for Next.js developers. Node-powered. WebView-thin. No Rust. No Chromium.",
5
5
  "keywords": [
6
6
  "desktop",
@@ -28,29 +28,31 @@
28
28
  },
29
29
  "exports": {
30
30
  ".": {
31
- "types": "./src/index.ts",
32
- "default": "./src/index.ts"
31
+ "types": "./dist/index.d.ts",
32
+ "default": "./dist/index.js"
33
33
  },
34
34
  "./jsx": {
35
- "types": "./src/jsx/index.ts",
36
- "default": "./src/jsx/index.ts"
35
+ "types": "./dist/jsx/index.d.ts",
36
+ "default": "./dist/jsx/index.js"
37
37
  },
38
38
  "./jsx-runtime": {
39
- "types": "./src/jsx/jsx-runtime.ts",
40
- "default": "./src/jsx/jsx-runtime.ts"
39
+ "types": "./dist/jsx/jsx-runtime.d.ts",
40
+ "default": "./dist/jsx/jsx-runtime.js"
41
41
  },
42
42
  "./jsx-dev-runtime": {
43
- "types": "./src/jsx/jsx-dev-runtime.ts",
44
- "default": "./src/jsx/jsx-dev-runtime.ts"
43
+ "types": "./dist/jsx/jsx-dev-runtime.d.ts",
44
+ "default": "./dist/jsx/jsx-dev-runtime.js"
45
45
  }
46
46
  },
47
47
  "files": [
48
48
  "bin",
49
- "src",
49
+ "dist",
50
50
  "README.md",
51
51
  "LICENSE"
52
52
  ],
53
53
  "scripts": {
54
+ "build": "tsc -p tsconfig.build.json",
55
+ "prepublishOnly": "pnpm run build",
54
56
  "example:app-router": "cd examples/app-router && pnpm dev",
55
57
  "check": "biome check",
56
58
  "lint": "biome lint",
package/src/cli/colors.ts DELETED
@@ -1,16 +0,0 @@
1
- // ANSI truecolor palette (Oomurasaki) + helper.
2
-
3
- export const BRIGHT = '\x1b[38;2;168;85;247m'
4
- export const DEEP = '\x1b[38;2;91;33;182m'
5
- export const CREAM = '\x1b[38;2;250;245;232m'
6
- export const DARK = '\x1b[38;2;59;7;100m'
7
- export const DIM = '\x1b[38;2;136;136;153m'
8
- export const GREEN = '\x1b[38;2;76;175;80m'
9
- export const RED = '\x1b[38;2;239;68;68m'
10
- export const BOLD = '\x1b[1m'
11
- export const RESET = '\x1b[0m'
12
-
13
- export const noColor = Boolean(process.env.NO_COLOR) || !process.stdout.isTTY
14
-
15
- /** Wrap an ANSI escape; returns '' if colors are disabled. */
16
- export const c = (code: string): string => (noColor ? '' : code)
package/src/cli/log.ts DELETED
@@ -1,42 +0,0 @@
1
- // Banner + status output for the dev runner.
2
-
3
- import { projectRoot, VERSION, WEBVIEW_ENGINE } from '../env.ts'
4
- import { BOLD, BRIGHT, c, DIM, GREEN, RED, RESET } from './colors.ts'
5
-
6
- const out = (s: string) => process.stdout.write(s)
7
-
8
- export function printBanner(winTitle: string, winSize: { width: number; height: number }) {
9
- out('\n')
10
- out(` ${c(BOLD)}${c(BRIGHT)}🦋 Murasaki${c(RESET)} ${c(DIM)}${VERSION}${c(RESET)}\n\n`)
11
- out(` ${c(DIM)}-${c(RESET)} ${c(DIM)}Project ${c(RESET)}${projectRoot}\n`)
12
- out(
13
- ` ${c(DIM)}-${c(RESET)} ${c(DIM)}Window ${c(RESET)}${winTitle} ${c(DIM)}(${winSize.width}×${winSize.height})${c(RESET)}\n`,
14
- )
15
- out(` ${c(DIM)}-${c(RESET)} ${c(DIM)}Webview ${c(RESET)}${WEBVIEW_ENGINE}\n`)
16
- out(` ${c(DIM)}-${c(RESET)} ${c(DIM)}Runtime ${c(RESET)}Node ${process.version}\n`)
17
- out(
18
- ` ${c(DIM)}-${c(RESET)} ${c(DIM)}Mode ${c(RESET)}development ${c(DIM)}(HMR active)${c(RESET)}\n\n`,
19
- )
20
- }
21
-
22
- export function printShortcuts() {
23
- out(
24
- ` ${c(DIM)}Shortcuts ${c(RESET)}${c(BOLD)}o${c(RESET)} ${c(DIM)}open${c(RESET)} ${c(BOLD)}r${c(RESET)} ${c(DIM)}restart${c(RESET)} ${c(BOLD)}q${c(RESET)} ${c(DIM)}quit${c(RESET)}\n\n`,
25
- )
26
- }
27
-
28
- export const printStarting = () => out(` ${c(DIM)}○${c(RESET)} Starting...\n`)
29
- export const printReady = (ms: number) =>
30
- out(
31
- ` ${c(GREEN)}${c(BOLD)}✓${c(RESET)} ${c(BOLD)}Ready${c(RESET)} ${c(DIM)}in ${ms}ms${c(RESET)}\n`,
32
- )
33
- export const printOpened = () => out(` ${c(GREEN)}${c(BOLD)}✓${c(RESET)} Window opened\n`)
34
- export const printClosed = () =>
35
- out(
36
- ` ${c(DIM)}○${c(RESET)} Window closed ${c(DIM)}— press ${c(RESET)}${c(BOLD)}o${c(RESET)}${c(DIM)} to re-open, ${c(RESET)}${c(BOLD)}q${c(RESET)}${c(DIM)} to quit${c(RESET)}\n`,
37
- )
38
- export const printReloaded = (file: string) =>
39
- out(` ${c(BRIGHT)}${c(BOLD)}↻${c(RESET)} Reloaded ${c(DIM)}${file}${c(RESET)}\n`)
40
- export const printBye = () => out(`\n ${c(DIM)}Bye 🦋${c(RESET)}\n\n`)
41
- export const printHint = (msg: string) => out(` ${c(DIM)}· ${msg}${c(RESET)}\n`)
42
- export const printError = (msg: string) => out(` ${c(RED)}${c(BOLD)}✗${c(RESET)} ${msg}\n`)
@@ -1,25 +0,0 @@
1
- // <Link href="/about">About</Link>
2
- //
3
- // Emits a plain <a> tagged with data-murasaki-link. The dev runner injects
4
- // a tiny script that intercepts clicks on these and switches the visible
5
- // route block in place — no full reload, no flash.
6
-
7
- import { jsx } from '../jsx/runtime.ts'
8
- import type { Child } from '../jsx/types.ts'
9
-
10
- export type LinkProps = {
11
- href: string
12
- children?: Child
13
- className?: string
14
- // Pass-through anchor props
15
- [key: string]: unknown
16
- }
17
-
18
- export function Link({ href, children, ...rest }: LinkProps) {
19
- return jsx('a', {
20
- href: `#${href}`,
21
- 'data-murasaki-link': href,
22
- ...rest,
23
- children,
24
- })
25
- }
package/src/dev.tsx DELETED
@@ -1,60 +0,0 @@
1
- // src/dev.tsx
2
- // Murasaki dev runner — Next.js-like file-based routing without Next.js.
3
- //
4
- // Reads the consumer's src/ directory:
5
- // src/layout.tsx (optional, can export `metadata`)
6
- // src/app.tsx (required)
7
- // src/globals.css (optional, auto-injected)
8
- //
9
- // Renders <Layout><App /></Layout> with React, ships HTML to the WebView,
10
- // and reloads in place on file change.
11
-
12
- import {
13
- printBanner,
14
- printBye,
15
- printOpened,
16
- printReady,
17
- printShortcuts,
18
- printStarting,
19
- } from './cli/log.ts'
20
- import { setupHmr } from './runtime/hmr.ts'
21
- import { setupShortcuts, teardownStdin } from './runtime/shortcuts.ts'
22
- import {
23
- closeWindow,
24
- exitApp,
25
- getConfig,
26
- openWindow,
27
- reloadWindow,
28
- runApp,
29
- } from './runtime/window.ts'
30
-
31
- const startAt = Date.now()
32
-
33
- // Boot: render once (applies metadata) → banner → ready
34
- await openWindow()
35
- printBanner(getConfig().title, getConfig())
36
- printShortcuts()
37
- printStarting()
38
- printReady(Date.now() - startAt)
39
-
40
- setupShortcuts({
41
- onOpen: () => {
42
- void openWindow().then(printOpened)
43
- },
44
- onRestart: () => {
45
- closeWindow()
46
- void openWindow().then(printOpened)
47
- },
48
- onQuit: () => {
49
- printBye()
50
- teardownStdin()
51
- exitApp()
52
- process.exit(0)
53
- },
54
- })
55
-
56
- setupHmr((file) => {
57
- void reloadWindow(file)
58
- })
59
-
60
- runApp()
package/src/env.ts DELETED
@@ -1,48 +0,0 @@
1
- // Project paths + version + platform — resolved once at boot.
2
-
3
- import { readFileSync } from 'node:fs'
4
- import { dirname, join } from 'node:path'
5
- import { fileURLToPath } from 'node:url'
6
-
7
- export const projectRoot = process.cwd()
8
- export const SRC_DIR = join(projectRoot, 'src')
9
-
10
- // App-router convention (new, preferred):
11
- // src/app/page.tsx → "/"
12
- // src/app/layout.tsx → root layout (html/head/body)
13
- // src/app/<sub>/page.tsx → "/<sub>"
14
- // src/app/globals.css → auto-injected
15
- export const APP_DIR = join(SRC_DIR, 'app')
16
- export const APP_GLOBALS_CSS = join(APP_DIR, 'globals.css')
17
-
18
- // Legacy single-page convention (still supported):
19
- // src/app.tsx + src/layout.tsx + src/globals.css
20
- export const LEGACY_APP_PATH = join(SRC_DIR, 'app.tsx')
21
- export const LEGACY_LAYOUT_PATH = join(SRC_DIR, 'layout.tsx')
22
- export const LEGACY_GLOBALS_CSS = join(SRC_DIR, 'globals.css')
23
-
24
- const __dirname = dirname(fileURLToPath(import.meta.url))
25
- export const VERSION: string = (() => {
26
- try {
27
- const pkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf8'))
28
- return pkg.version || '0.0.0'
29
- } catch {
30
- return '0.0.0'
31
- }
32
- })()
33
-
34
- export const WEBVIEW_ENGINE: string = (() => {
35
- switch (process.platform) {
36
- case 'darwin':
37
- return 'WKWebView (macOS)'
38
- case 'win32':
39
- return 'WebView2 (Windows)'
40
- case 'linux':
41
- return 'WebKitGTK (Linux)'
42
- default:
43
- return `OS native (${process.platform})`
44
- }
45
- })()
46
-
47
- export const DEFAULT_WIN_TITLE = 'Murasaki App'
48
- export const DEFAULT_WIN_SIZE = { width: 1280, height: 800 }
package/src/index.ts DELETED
@@ -1,24 +0,0 @@
1
- // murasaki — public API
2
- //
3
- // Import like:
4
- // import type { Metadata } from 'murasaki'
5
- // import { Link } from 'murasaki'
6
-
7
- export type { LinkProps } from './components/Link.tsx'
8
- export { Link } from './components/Link.tsx'
9
-
10
- export type Metadata = {
11
- /** Default <title> for the app (overridden by <title> tag inside <head>) */
12
- title?: string
13
- /** <meta name="description"> */
14
- description?: string
15
- /** Initial window options (applied at first open; user can resize after) */
16
- window?: {
17
- /** Window title bar text (defaults to metadata.title) */
18
- title?: string
19
- /** Initial width in logical pixels */
20
- width?: number
21
- /** Initial height in logical pixels */
22
- height?: number
23
- }
24
- }
package/src/jsx/index.ts DELETED
@@ -1,21 +0,0 @@
1
- // Public surface for `import { ... } from 'murasaki/jsx'`.
2
-
3
- export {
4
- createElement,
5
- Fragment,
6
- isJSXNode,
7
- isValidElement,
8
- JSXNode,
9
- jsx,
10
- raw,
11
- renderToString,
12
- } from './runtime.ts'
13
-
14
- export type {
15
- Child,
16
- Component,
17
- Element,
18
- FC,
19
- JSXNodeLike,
20
- Props,
21
- } from './types.ts'
@@ -1,6 +0,0 @@
1
- // JSX dev runtime entry — used when tsconfig has `jsx: "react-jsxdev"`.
2
- // We don't (yet) track source locations or component stacks, so jsxDEV
3
- // behaves identically to jsx.
4
-
5
- export { Fragment, jsx as jsxDEV } from './runtime.ts'
6
- export type { JSX } from './types.ts'