jsmdcui 0.10.1 → 0.11.2

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/CHANGELOG.md CHANGED
@@ -2,6 +2,79 @@
2
2
 
3
3
  All notable user-visible changes to jsmdcui are documented here.
4
4
 
5
+ ## [0.11.2] - 2026-07-26
6
+
7
+ ### Added
8
+
9
+ - Add `--build-md-exe <file.md>` as a convenience alias for building a
10
+ current-platform executable with `global.MDCUI_MAIN` set to the specified
11
+ Markdown app.
12
+ - Add `--build-md-for <platform> <file.md>` for the equivalent
13
+ cross-compilation workflow. Both aliases expand into the existing build
14
+ arguments before generated application files are written.
15
+
16
+ ### Fixed
17
+
18
+ - Fix the final executable existence check for Windows builds by checking the
19
+ `.exe` output path for Windows targets, or for native Windows builds when no
20
+ target is specified.
21
+
22
+ ## [0.11.1] - 2026-07-26
23
+
24
+ ### Changed
25
+
26
+ - Accept a bare `global.MDCUI_MAIN` path in forwarded build arguments by
27
+ automatically encoding non-primitive define values as JavaScript strings.
28
+
29
+ ## [0.11.0] - 2026-07-26
30
+
31
+ This release adds custom Markdown-app embedding for Bun single-file
32
+ executables, with explicit per-buffer selection between embedded and
33
+ filesystem modules in both TUI and WUI.
34
+
35
+ ### Added
36
+
37
+ - Add the build-time `global.MDCUI_MAIN` string define for embedding a custom
38
+ Markdown app together with its generated front, RPC, back, HTML, and server
39
+ modules. Build preparation resolves and validates the source, copies it into
40
+ the bundled demos, derives `global.MDCUI_MAIN_BASE`, and selects the app on a
41
+ no-argument launch.
42
+ - Add a bundling mode to `extractJs()` and `createWui()`. It emits a
43
+ browser-only `.tmpfs.js` front module and a `.tmpfi.js` installer that exposes
44
+ the front exports on `window`, then makes the bundled HTML load that entry.
45
+ - Add embedded WUI server startup and report whether WUI is starting an
46
+ embedded or external server before launch.
47
+ - Add `micro.CurPane().Buf.MdcuiModuleSource`, returning `embedded` or
48
+ `external`, and show the value in the bundled `showpath` example.
49
+ - Allow Unicode letters and numbers, including Chinese, in custom demo names
50
+ while continuing to reject whitespace and path separators.
51
+ - Show `global.MDCUI_MAIN` and the generated `global.MDCUI_MAIN_BASE` in
52
+ `--version` distribution settings.
53
+
54
+ ### Changed
55
+
56
+ - Track embedded-module selection per buffer. The configured demo uses
57
+ embedded TUI front/RPC and WUI server modules when its local byte length
58
+ matches the bundled Markdown. Missing or overwritten copies are written
59
+ first and then use embedded modules; other files and changed-size demos use
60
+ filesystem companions.
61
+ - Document presence-based `MDCUI_*` defines with `=1`, supported build-flag
62
+ combinations, and commands for switching a TUI-default build to WUI or a
63
+ WUI-default build to TUI.
64
+
65
+ ### Fixed
66
+
67
+ - Bundle and load the configured app's front, RPC, back, server, and dependency
68
+ graph so custom apps with companion imports can run from a single
69
+ executable.
70
+ - Keep unrelated Markdown buffers on external modules instead of reusing the
71
+ embedded main app's front and RPC modules.
72
+ - Use the bundled file's byte length after `MDCUI_OVERWRITE_DEMO` replaces a
73
+ stale local demo, ensuring that the overwritten app selects embedded
74
+ modules.
75
+ - Install WUI front exports on `window` without relying on the generated front
76
+ module's process-dependent or self-import path.
77
+
5
78
  ## [0.10.1] - 2026-07-25
6
79
 
7
80
  ### Fixed
package/README.md CHANGED
@@ -757,54 +757,113 @@ both are equivalent to `-encoding mdcui`.
757
757
 
758
758
  ### Build-time distribution constants
759
759
 
760
- Single-file distributions can define one of these default modes:
760
+ The following switch defines are presence-based: the program checks whether
761
+ they were passed, not whether their values are true. Consequently, `=0` and
762
+ `=false` still enable a switch. Omit a define entirely to disable it. Examples
763
+ use `=1` to make this explicit.
761
764
 
762
- - `MDCUI_DEFAULT_EDIT`: open files as editable text by default.
763
- - `MDCUI_DEFAULT_DEMO`: add `--demo` when launched without arguments.
764
- - `MDCUI_DEFAULT_DEMO_WUI`: add `--wui` when launched without arguments.
765
+ - `MDCUI_DEFAULT_EDIT=1`: open files as editable text by default.
766
+ - `MDCUI_DEFAULT_DEMO=1`: add `--demo` when launched without arguments.
767
+ - `MDCUI_DEFAULT_DEMO_WUI=1`: add `--wui` when launched without arguments.
768
+ - `MDCUI_OVERWRITE_DEMO=1`: add `--overwrite-demo`; this modifies a selected
769
+ demo but does not select one by itself.
770
+ - `global.MDCUI_MAIN=<path>.md`: embed a custom Markdown application and its
771
+ generated front, RPC, back, HTML, and server modules. When this define is
772
+ forwarded after `--build-exe` or `--build-for`, a non-primitive value such as
773
+ a bare path is automatically encoded as a JavaScript string. An explicitly
774
+ quoted string remains supported.
775
+ - `global.MDCUI_MAIN_BASE`: internal define generated automatically from
776
+ `global.MDCUI_MAIN`; do not pass it manually.
765
777
 
766
- Choose only one of the three default-mode constants for a distribution.
767
- `MDCUI_OVERWRITE_DEMO` is an optional modifier for the demo or WUI mode.
768
- These are presence-based constants, so their build values do not require
769
- shell-quoted strings:
778
+ For the current platform, build an executable embedding `myapp.md` with:
770
779
 
771
- ```sh
772
- bun src/index.js --build-exe --define MDCUI_DEFAULT_EDIT=true
780
+ ```shell
781
+ npx jsmdcui --build-md-exe myapp.md
782
+ ```
783
+
784
+ This is a convenience alias for
785
+ `--build-exe --define global.MDCUI_MAIN=myapp.md`.
786
+
787
+ For cross-compilation, specify the Bun target before the Markdown file:
788
+
789
+ ```shell
790
+ npx jsmdcui --build-md-for bun-linux-x64-v1.3.14 myapp.md
773
791
  ```
774
792
 
775
- ### Ship `testapp.md` as a standalone application
793
+ This similarly expands to
794
+ `--build-for bun-linux-x64 --define global.MDCUI_MAIN=myapp.md`. Both aliases
795
+ are expanded before any generated application files are written.
796
+
797
+ Place every build define after `--build-exe`, or after the target argument of
798
+ `--build-for`. Choose at most one of `MDCUI_DEFAULT_EDIT`,
799
+ `MDCUI_DEFAULT_DEMO`, and `MDCUI_DEFAULT_DEMO_WUI`.
800
+
801
+ | Build defines | No-argument launch | Open the same app in the other UI |
802
+ | --- | --- | --- |
803
+ | none | normal CLI/TUI | `./mdcui --wui app.md` |
804
+ | `MDCUI_DEFAULT_EDIT=1` | text editor | `./mdcui --tui app.md` |
805
+ | `MDCUI_DEFAULT_DEMO=1` | `testapp.md` TUI | `./mdcui --wui --demo` |
806
+ | `MDCUI_DEFAULT_DEMO_WUI=1` | `testapp.md` WUI | `./mdcui --tui --demo` |
807
+ | `global.MDCUI_MAIN=../中文工具.md` | embedded custom TUI | `./mdcui --wui --demo-中文工具` |
808
+ | MAIN plus `MDCUI_DEFAULT_DEMO_WUI=1` | embedded custom WUI | `./mdcui --tui --demo-中文工具` |
809
+
810
+ Any explicit runtime argument suppresses the no-argument demo/WUI injection.
811
+ That is why the commands in the last column repeat `--demo` or
812
+ `--demo-中文工具`; `./mdcui --wui` by itself does not implicitly select a custom
813
+ main application.
776
814
 
777
- To turn your finished Markdown UI into a standalone executable, save it as the
778
- repository-root `testapp.md`, then build with both demo constants:
815
+ To package `../中文工具.md` as a TUI by default:
779
816
 
780
817
  ```sh
781
818
  bun src/index.js --build-exe \
782
- --define MDCUI_DEFAULT_DEMO=true \
783
- --define MDCUI_OVERWRITE_DEMO=true
819
+ --define global.MDCUI_MAIN=../中文工具.md
820
+
821
+ ./mdcui
822
+ ./mdcui --wui --demo-中文工具
823
+ ```
824
+
825
+ To package the same application as a WUI by default and explicitly switch back
826
+ to its TUI:
827
+
828
+ ```sh
829
+ bun src/index.js --build-exe \
830
+ --define global.MDCUI_MAIN=../中文工具.md \
831
+ --define MDCUI_DEFAULT_DEMO_WUI=1
832
+
833
+ ./mdcui
834
+ ./mdcui --tui --demo-中文工具
784
835
  ```
785
836
 
786
- The build first packs `testapp.md` into the executable and writes the resulting
787
- `mdcui` binary in the current directory. In that binary,
788
- `MDCUI_DEFAULT_DEMO` adds `--demo` when the user launches it without arguments,
789
- and `MDCUI_OVERWRITE_DEMO` adds `--overwrite-demo`. Consequently, running
790
- `./mdcui` writes the bundled application to `./testapp.md`, replacing an older
791
- copy, and starts it as the terminal UI.
837
+ The `MDCUI_MAIN` basename must end with lowercase `.md`. Its demo-name portion
838
+ must start with a Unicode letter or number and may contain Unicode
839
+ letters/numbers (including Chinese), combining marks, dots, underscores, and
840
+ hyphens. Whitespace and path separators are not allowed.
841
+
842
+ When the configured custom demo is selected and its local Markdown byte length
843
+ matches the embedded copy, TUI uses the embedded front/RPC modules and WUI uses
844
+ the embedded server. A missing demo, or one selected with
845
+ `MDCUI_OVERWRITE_DEMO=1`, is first written from the embedded copy and then uses
846
+ embedded modules. A different byte length prints a warning and uses filesystem
847
+ companion modules. Directly opening `./mdcui app.md` or
848
+ `./mdcui --wui app.md` has no demo provenance and therefore uses filesystem
849
+ modules even if the basename matches `MDCUI_MAIN`.
792
850
 
793
- To make a no-argument launch start the browser UI instead, build with
794
- `MDCUI_DEFAULT_DEMO_WUI`:
851
+ To retain the older repository-root `testapp.md` distribution instead, build a
852
+ TUI with:
795
853
 
796
854
  ```sh
797
855
  bun src/index.js --build-exe \
798
- --define MDCUI_DEFAULT_DEMO_WUI=true \
799
- --define MDCUI_OVERWRITE_DEMO=true
856
+ --define MDCUI_DEFAULT_DEMO=1 \
857
+ --define MDCUI_OVERWRITE_DEMO=1
800
858
  ```
801
859
 
802
- This adds `--wui` when the executable is launched without arguments.
860
+ For a default WUI, replace `MDCUI_DEFAULT_DEMO` with
861
+ `MDCUI_DEFAULT_DEMO_WUI`.
803
862
 
804
863
  You can rename and distribute the resulting binary. It contains the Bun
805
- runtime, jsmdcui, the packed runtime assets, and your `testapp.md`; the target
806
- directory must remain writable because launching the application creates
807
- `testapp.md` and its generated companion files there.
864
+ runtime, jsmdcui, the packed runtime assets, and the configured demo or custom
865
+ main application. The target directory must remain writable because launching
866
+ an application creates its Markdown file and generated companion files there.
808
867
 
809
868
  ## Development
810
869
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jsmdcui",
3
- "version": "0.10.1",
3
+ "version": "0.11.2",
4
4
  "description": "Markdown as a Common UI for Terminals and Web Browsers",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
package/runmd.mjs CHANGED
@@ -54,6 +54,7 @@ export async function main(tuiWidth=30, {
54
54
  mdpath: requestedMdpath = null,
55
55
  overwriteDemo = process.argv.includes("--overwrite-demo"),
56
56
  printUi = process.argv.includes("--print-ui"),
57
+ useBundledMdcuiServer = false,
57
58
  } = {})
58
59
  {
59
60
  const explicitMdpath = process.argv.find(i=>i.endsWith('.md'))
@@ -99,7 +100,20 @@ export async function main(tuiWidth=30, {
99
100
 
100
101
 
101
102
  const serverPath = mdpath + "-server.js"
102
- const svmod = await import(pathToFileURL(path.resolve(serverPath)).href)
103
+ const useEmbeddedMdcuiServer = Boolean(
104
+ global.MDCUI_MAIN && useBundledMdcuiServer
105
+ )
106
+ cse(
107
+ `[mdcui] Starting ${useEmbeddedMdcuiServer ? "embedded" : "external"} `
108
+ + `WUI server: ${
109
+ useEmbeddedMdcuiServer
110
+ ? String(global.MDCUI_MAIN)
111
+ : path.resolve(serverPath)
112
+ }`
113
+ )
114
+ const svmod = useEmbeddedMdcuiServer
115
+ ? await import(global.MDCUI_MAIN + "-server.js")
116
+ : await import(pathToFileURL(path.resolve(serverPath)).href)
103
117
 
104
118
  cse("\n\n"+mda('# Server'))
105
119
  svmod.main();
@@ -109,7 +123,7 @@ export async function main(tuiWidth=30, {
109
123
  // Exports
110
124
 
111
125
 
112
- export async function extractJs(md,mdpath)
126
+ export async function extractJs(md,mdpath,{ bundling = false } = {})
113
127
  {
114
128
  const mdb = path.basename(mdpath)
115
129
 
@@ -128,16 +142,23 @@ export async function extractJs(md,mdpath)
128
142
  }
129
143
  )
130
144
 
145
+ const frontSource = sctags
131
146
  sctags = "#!/usr/bin/env bun" + `
132
147
 
133
148
  import { rpc as wuiRpcClient } from "./${mdb}-rpc.js";
134
- let rpc = "${mdb}"
149
+ let rpc = null
135
150
  if(globalThis.process)
136
- rpc = await import("./"+rpc+".back.js") ;
151
+ {
152
+ rpc = await import(
153
+ "./" +
154
+ (global.MDCUI_MAIN_BASE||"${mdb}") +
155
+ ".back.js"
156
+ ) ;
157
+ }
137
158
  else
138
159
  rpc = wuiRpcClient ;
139
160
 
140
- ` + sctags + `
161
+ ` + frontSource + `
141
162
 
142
163
  if (typeof window !== "undefined")
143
164
  {
@@ -152,6 +173,28 @@ export async function extractJs(md,mdpath)
152
173
 
153
174
  await Bun.write(sctagsp,sctags);
154
175
  logWroteFile("front", sctagsp)
176
+
177
+ if (bundling) {
178
+ const bundledFrontSource = "#!/usr/bin/env bun" + `
179
+
180
+ import { rpc as wuiRpcClient } from "./${mdb}-rpc.js";
181
+ const rpc = wuiRpcClient;
182
+
183
+ ` + frontSource
184
+ const bundledFrontPath = mdpath + ".tmpfs.js"
185
+ await Bun.write(bundledFrontPath, bundledFrontSource)
186
+ logWroteFile("bundling front", bundledFrontPath)
187
+
188
+ const bundledImportPath = mdpath + ".tmpfi.js"
189
+ await Bun.write(
190
+ bundledImportPath,
191
+ `import * as frontMod from "./${mdb}.tmpfs.js";
192
+
193
+ Object.assign(window, frontMod);
194
+ `,
195
+ )
196
+ logWroteFile("bundling import", bundledImportPath)
197
+ }
155
198
 
156
199
  sctagsp = mdpath + ".back.js"
157
200
  sctags = "#!/usr/bin/env bun\n\n"
@@ -354,7 +397,7 @@ export function wrapWuiHeadingSections(html)
354
397
  return output;
355
398
  }
356
399
 
357
- export async function createWui(md,mdpath) // HTML
400
+ export async function createWui(md,mdpath,{ bundling = false } = {}) // HTML
358
401
  {
359
402
  const eventsById = fenceEventMap(md)
360
403
 
@@ -397,7 +440,8 @@ img {
397
440
  height: auto;
398
441
  }
399
442
  </style>`;
400
- const moduleScript = `<scr`+`ipt type="module" src="./${mdb}.front.js"></scr`+`ipt>`;
443
+ const moduleEntry = bundling ? `${mdb}.tmpfi.js` : `${mdb}.front.js`;
444
+ const moduleScript = `<scr`+`ipt type="module" src="./${moduleEntry}"></scr`+`ipt>`;
401
445
  const isFullHtmlDocument = /^\s*<!doctype html>/i.test(md);
402
446
  if (!isFullHtmlDocument) {
403
447
  md = `<!doctype html>
@@ -757,54 +757,113 @@ both are equivalent to `-encoding mdcui`.
757
757
 
758
758
  ### Build-time distribution constants
759
759
 
760
- Single-file distributions can define one of these default modes:
760
+ The following switch defines are presence-based: the program checks whether
761
+ they were passed, not whether their values are true. Consequently, `=0` and
762
+ `=false` still enable a switch. Omit a define entirely to disable it. Examples
763
+ use `=1` to make this explicit.
761
764
 
762
- - `MDCUI_DEFAULT_EDIT`: open files as editable text by default.
763
- - `MDCUI_DEFAULT_DEMO`: add `--demo` when launched without arguments.
764
- - `MDCUI_DEFAULT_DEMO_WUI`: add `--wui` when launched without arguments.
765
+ - `MDCUI_DEFAULT_EDIT=1`: open files as editable text by default.
766
+ - `MDCUI_DEFAULT_DEMO=1`: add `--demo` when launched without arguments.
767
+ - `MDCUI_DEFAULT_DEMO_WUI=1`: add `--wui` when launched without arguments.
768
+ - `MDCUI_OVERWRITE_DEMO=1`: add `--overwrite-demo`; this modifies a selected
769
+ demo but does not select one by itself.
770
+ - `global.MDCUI_MAIN=<path>.md`: embed a custom Markdown application and its
771
+ generated front, RPC, back, HTML, and server modules. When this define is
772
+ forwarded after `--build-exe` or `--build-for`, a non-primitive value such as
773
+ a bare path is automatically encoded as a JavaScript string. An explicitly
774
+ quoted string remains supported.
775
+ - `global.MDCUI_MAIN_BASE`: internal define generated automatically from
776
+ `global.MDCUI_MAIN`; do not pass it manually.
765
777
 
766
- Choose only one of the three default-mode constants for a distribution.
767
- `MDCUI_OVERWRITE_DEMO` is an optional modifier for the demo or WUI mode.
768
- These are presence-based constants, so their build values do not require
769
- shell-quoted strings:
778
+ For the current platform, build an executable embedding `myapp.md` with:
770
779
 
771
- ```sh
772
- bun src/index.js --build-exe --define MDCUI_DEFAULT_EDIT=true
780
+ ```shell
781
+ npx jsmdcui --build-md-exe myapp.md
782
+ ```
783
+
784
+ This is a convenience alias for
785
+ `--build-exe --define global.MDCUI_MAIN=myapp.md`.
786
+
787
+ For cross-compilation, specify the Bun target before the Markdown file:
788
+
789
+ ```shell
790
+ npx jsmdcui --build-md-for bun-linux-x64-v1.3.14 myapp.md
773
791
  ```
774
792
 
775
- ### Ship `testapp.md` as a standalone application
793
+ This similarly expands to
794
+ `--build-for bun-linux-x64 --define global.MDCUI_MAIN=myapp.md`. Both aliases
795
+ are expanded before any generated application files are written.
796
+
797
+ Place every build define after `--build-exe`, or after the target argument of
798
+ `--build-for`. Choose at most one of `MDCUI_DEFAULT_EDIT`,
799
+ `MDCUI_DEFAULT_DEMO`, and `MDCUI_DEFAULT_DEMO_WUI`.
800
+
801
+ | Build defines | No-argument launch | Open the same app in the other UI |
802
+ | --- | --- | --- |
803
+ | none | normal CLI/TUI | `./mdcui --wui app.md` |
804
+ | `MDCUI_DEFAULT_EDIT=1` | text editor | `./mdcui --tui app.md` |
805
+ | `MDCUI_DEFAULT_DEMO=1` | `testapp.md` TUI | `./mdcui --wui --demo` |
806
+ | `MDCUI_DEFAULT_DEMO_WUI=1` | `testapp.md` WUI | `./mdcui --tui --demo` |
807
+ | `global.MDCUI_MAIN=../中文工具.md` | embedded custom TUI | `./mdcui --wui --demo-中文工具` |
808
+ | MAIN plus `MDCUI_DEFAULT_DEMO_WUI=1` | embedded custom WUI | `./mdcui --tui --demo-中文工具` |
809
+
810
+ Any explicit runtime argument suppresses the no-argument demo/WUI injection.
811
+ That is why the commands in the last column repeat `--demo` or
812
+ `--demo-中文工具`; `./mdcui --wui` by itself does not implicitly select a custom
813
+ main application.
776
814
 
777
- To turn your finished Markdown UI into a standalone executable, save it as the
778
- repository-root `testapp.md`, then build with both demo constants:
815
+ To package `../中文工具.md` as a TUI by default:
779
816
 
780
817
  ```sh
781
818
  bun src/index.js --build-exe \
782
- --define MDCUI_DEFAULT_DEMO=true \
783
- --define MDCUI_OVERWRITE_DEMO=true
819
+ --define global.MDCUI_MAIN=../中文工具.md
820
+
821
+ ./mdcui
822
+ ./mdcui --wui --demo-中文工具
823
+ ```
824
+
825
+ To package the same application as a WUI by default and explicitly switch back
826
+ to its TUI:
827
+
828
+ ```sh
829
+ bun src/index.js --build-exe \
830
+ --define global.MDCUI_MAIN=../中文工具.md \
831
+ --define MDCUI_DEFAULT_DEMO_WUI=1
832
+
833
+ ./mdcui
834
+ ./mdcui --tui --demo-中文工具
784
835
  ```
785
836
 
786
- The build first packs `testapp.md` into the executable and writes the resulting
787
- `mdcui` binary in the current directory. In that binary,
788
- `MDCUI_DEFAULT_DEMO` adds `--demo` when the user launches it without arguments,
789
- and `MDCUI_OVERWRITE_DEMO` adds `--overwrite-demo`. Consequently, running
790
- `./mdcui` writes the bundled application to `./testapp.md`, replacing an older
791
- copy, and starts it as the terminal UI.
837
+ The `MDCUI_MAIN` basename must end with lowercase `.md`. Its demo-name portion
838
+ must start with a Unicode letter or number and may contain Unicode
839
+ letters/numbers (including Chinese), combining marks, dots, underscores, and
840
+ hyphens. Whitespace and path separators are not allowed.
841
+
842
+ When the configured custom demo is selected and its local Markdown byte length
843
+ matches the embedded copy, TUI uses the embedded front/RPC modules and WUI uses
844
+ the embedded server. A missing demo, or one selected with
845
+ `MDCUI_OVERWRITE_DEMO=1`, is first written from the embedded copy and then uses
846
+ embedded modules. A different byte length prints a warning and uses filesystem
847
+ companion modules. Directly opening `./mdcui app.md` or
848
+ `./mdcui --wui app.md` has no demo provenance and therefore uses filesystem
849
+ modules even if the basename matches `MDCUI_MAIN`.
792
850
 
793
- To make a no-argument launch start the browser UI instead, build with
794
- `MDCUI_DEFAULT_DEMO_WUI`:
851
+ To retain the older repository-root `testapp.md` distribution instead, build a
852
+ TUI with:
795
853
 
796
854
  ```sh
797
855
  bun src/index.js --build-exe \
798
- --define MDCUI_DEFAULT_DEMO_WUI=true \
799
- --define MDCUI_OVERWRITE_DEMO=true
856
+ --define MDCUI_DEFAULT_DEMO=1 \
857
+ --define MDCUI_OVERWRITE_DEMO=1
800
858
  ```
801
859
 
802
- This adds `--wui` when the executable is launched without arguments.
860
+ For a default WUI, replace `MDCUI_DEFAULT_DEMO` with
861
+ `MDCUI_DEFAULT_DEMO_WUI`.
803
862
 
804
863
  You can rename and distribute the resulting binary. It contains the Bun
805
- runtime, jsmdcui, the packed runtime assets, and your `testapp.md`; the target
806
- directory must remain writable because launching the application creates
807
- `testapp.md` and its generated companion files there.
864
+ runtime, jsmdcui, the packed runtime assets, and the configured demo or custom
865
+ main application. The target directory must remain writable because launching
866
+ an application creates its Markdown file and generated companion files there.
808
867
 
809
868
  ## Development
810
869
 
@@ -69,8 +69,10 @@ micro.on("init", () => {
69
69
 
70
70
  //micro.alert(micro.getLine())
71
71
  const path = bp?.Buf?.Path || "(no path)";
72
+ const moduleSource =
73
+ micro.CurPane()?.Buf?.MdcuiModuleSource || "external";
72
74
  const loc = bp?.CursorLocation?.() || "+1.0:1";
73
- micro.alert(`${path}\n${loc}`)
75
+ micro.alert(`${path}\nMdcuiModuleSource: ${moduleSource}\n${loc}`)
74
76
 
75
77
  });
76
78
 
@@ -39,42 +39,58 @@ bun ./src/index.js --build-exe --sourcemap
39
39
  bun ./src/index.js --build-for <target> --sourcemap
40
40
  ```
41
41
 
42
- The following presence-based build constants select distribution defaults:
43
-
44
- - `MDCUI_DEFAULT_EDIT`: open files as editable text by default.
45
- - `MDCUI_DEFAULT_DEMO`: add `--demo` when launched without arguments.
46
- - `MDCUI_DEFAULT_DEMO_WUI`: add `--wui` when launched without arguments.
47
-
48
- Choose only one of these three default-mode constants for each build.
49
- `MDCUI_OVERWRITE_DEMO` is an optional modifier for a demo or WUI build.
50
-
51
- For example, build a default text editor with:
42
+ Bun expects `--define` values to be JSON-style literals, so strings normally
43
+ need quotes. `stringifyNonPrimitiveDefineValues()` converts a bare value with
44
+ `JSON.stringify()` before it reaches Bun. jsmdcui uses it for
45
+ `global.MDCUI_MAIN`.
46
+
47
+ The switch defines below are presence-based: `=0` and `=false` still enable
48
+ them. Omit a switch define to disable it; examples consistently use `=1`.
49
+
50
+ - `MDCUI_DEFAULT_EDIT=1`: editable-text default.
51
+ - `MDCUI_DEFAULT_DEMO=1`: no-argument `testapp.md` TUI.
52
+ - `MDCUI_DEFAULT_DEMO_WUI=1`: no-argument `testapp.md` WUI.
53
+ - `MDCUI_OVERWRITE_DEMO=1`: overwrite modifier; it does not select a demo.
54
+ - `global.MDCUI_MAIN=<path>.md`: embed a custom Markdown app and its generated
55
+ front, RPC, back, HTML, and server modules.
56
+ - `global.MDCUI_MAIN_BASE`: generated internally from `MDCUI_MAIN`; do not pass
57
+ it manually.
58
+
59
+ Put defines after `--build-exe` (or after the `--build-for` target), and choose
60
+ at most one `MDCUI_DEFAULT_*` mode.
61
+
62
+ | Build defines | No-argument launch | Switch UI |
63
+ | --- | --- | --- |
64
+ | `MDCUI_DEFAULT_EDIT=1` | text editor | `./mdcui --tui app.md` |
65
+ | `MDCUI_DEFAULT_DEMO=1` | `testapp.md` TUI | `./mdcui --wui --demo` |
66
+ | `MDCUI_DEFAULT_DEMO_WUI=1` | `testapp.md` WUI | `./mdcui --tui --demo` |
67
+ | `global.MDCUI_MAIN=../中文工具.md` | custom TUI | `./mdcui --wui --demo-中文工具` |
68
+ | MAIN plus `MDCUI_DEFAULT_DEMO_WUI=1` | custom WUI | `./mdcui --tui --demo-中文工具` |
69
+
70
+ For a custom TUI-default executable:
52
71
 
53
72
  ```shell
54
73
  bun ./src/index.js --build-exe \
55
- --define MDCUI_DEFAULT_EDIT=true
74
+ --define global.MDCUI_MAIN=../中文工具.md
56
75
  ```
57
76
 
58
- To build a bundled terminal demo that replaces its local copy:
77
+ For a custom WUI-default executable:
59
78
 
60
79
  ```shell
61
80
  bun ./src/index.js --build-exe \
62
- --define MDCUI_DEFAULT_DEMO=true \
63
- --define MDCUI_OVERWRITE_DEMO=true
81
+ --define global.MDCUI_MAIN=../中文工具.md \
82
+ --define MDCUI_DEFAULT_DEMO_WUI=1
64
83
  ```
65
84
 
66
- `MDCUI_DEFAULT_DEMO=true` makes an executable launched without arguments behave
67
- as if `--demo` was passed. `MDCUI_OVERWRITE_DEMO=true` makes every selected demo
68
- replace an existing local copy; it does not select a demo by itself.
69
-
70
- For a browser UI that automatically adds `--wui` when launched without
71
- arguments, use `MDCUI_DEFAULT_DEMO_WUI` instead:
85
+ Explicit runtime arguments suppress automatic demo/WUI selection, so switching
86
+ UI must repeat `--demo` or `--demo-中文工具`. The main basename must end in
87
+ lowercase `.md`; its demo name allows Unicode letters/numbers (including
88
+ Chinese), dots, underscores, and hyphens, but no whitespace.
72
89
 
73
- ```shell
74
- bun ./src/index.js --build-exe \
75
- --define MDCUI_DEFAULT_DEMO_WUI=true \
76
- --define MDCUI_OVERWRITE_DEMO=true
77
- ```
90
+ The custom demo uses embedded TUI front/RPC or the embedded WUI server when its
91
+ local Markdown byte length matches the embedded asset. Missing or overwritten
92
+ demos use embedded modules after the asset is written. A differing byte length
93
+ warns and selects filesystem companion modules.
78
94
 
79
95
  To perform the same steps manually, run these commands from `single-exe/`:
80
96
 
@@ -221,6 +237,47 @@ bun ./packAssets.sh
221
237
  bun build --format=esm --compile --minify --bytecode ./entry.mjs --outfile=my-bin
222
238
  ```
223
239
 
240
+ #### Passing --define to bun build
241
+
242
+ `buildEarlyExit()` forwards build arguments to Bun, whose define parser expects
243
+ strings to be quoted literals. To accept a bare value such as a path, call the below
244
+ helper to normalize it before `buildEarlyExit()`:
245
+
246
+ ```js
247
+ import {
248
+ buildEarlyExit,
249
+ stringifyNonPrimitiveDefineValues,
250
+ } from "../single-exe/compiled.js";
251
+
252
+ stringifyNonPrimitiveDefineValues(process.argv, "MY_STRING_DEFINE");
253
+ await buildEarlyExit(process.argv, "my-bin");
254
+ ```
255
+
256
+ ```shell
257
+ # Wrong: Bun parses the define before the helper runs.
258
+ bun --define MY_STRING_DEFINE=../app.md ./src/index.js --build-exe
259
+
260
+ # Correct
261
+ bun ./src/index.js --build-exe --define MY_STRING_DEFINE=../app.md
262
+ ```
263
+
264
+ Before normalization:
265
+
266
+ ```js
267
+ ["--define", "MY_STRING_DEFINE=../app.md"]
268
+ ```
269
+
270
+ After normalization:
271
+
272
+ ```js
273
+ ["--define", 'MY_STRING_DEFINE="../app.md"']
274
+ ```
275
+
276
+ The inline form works too:
277
+ `--define=MY_STRING_DEFINE=../app.md` becomes
278
+ `--define=MY_STRING_DEFINE="../app.md"`.
279
+
280
+
224
281
  ### 6. Verify both execution paths
225
282
 
226
283
  Verify the compiled asset archive and then run the program normally: