fpasoterm 1.6.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.
Potentially problematic release.
This version of fpasoterm might be problematic. Click here for more details.
- package/CHANGELOG.md +230 -0
- package/CONTRIBUTING.md +67 -0
- package/INSTALL.ja.md +204 -0
- package/INSTALL.md +229 -0
- package/LICENSE +21 -0
- package/README.ja.md +389 -0
- package/README.md +607 -0
- package/bin/fpasoterm +2882 -0
- package/completions/_fpasoterm +81 -0
- package/completions/fpasoterm.bash +55 -0
- package/completions/fpasoterm.fish +64 -0
- package/completions/fpasoterm.ps1 +47 -0
- package/docs/capability-diagnostics.en.md +77 -0
- package/docs/capability-diagnostics.ja.md +63 -0
- package/docs/completion.en.md +141 -0
- package/docs/completion.ja.md +113 -0
- package/docs/config.en.md +554 -0
- package/docs/config.ja.md +544 -0
- package/docs/debugging.en.md +72 -0
- package/docs/debugging.ja.md +66 -0
- package/docs/diagnostics.en.md +69 -0
- package/docs/diagnostics.ja.md +64 -0
- package/docs/font-diagnostics.en.md +116 -0
- package/docs/font-diagnostics.ja.md +105 -0
- package/docs/fpasoterm-plugin.d.ts +51 -0
- package/docs/known-issues.en.md +23 -0
- package/docs/known-issues.ja.md +23 -0
- package/docs/plugins.en.md +266 -0
- package/docs/plugins.ja.md +176 -0
- package/docs/pr-review.en.md +177 -0
- package/docs/pr-review.ja.md +170 -0
- package/docs/release-checklist.en.md +72 -0
- package/docs/release-checklist.ja.md +71 -0
- package/docs/security.en.md +36 -0
- package/docs/security.ja.md +31 -0
- package/docs/spec.en.md +106 -0
- package/docs/spec.ja.md +99 -0
- package/docs/sshfs.en.md +28 -0
- package/docs/sshfs.ja.md +28 -0
- package/docs/sync.en.md +280 -0
- package/docs/sync.ja.md +280 -0
- package/examples/apply-default-appearance.bat +8 -0
- package/examples/apply-default-appearance.ps1 +7 -0
- package/examples/apply-default-appearance.sh +7 -0
- package/examples/apply-runtime-appearance.bat +8 -0
- package/examples/apply-runtime-appearance.ps1 +7 -0
- package/examples/apply-runtime-appearance.sh +7 -0
- package/examples/config/default-appearance.toml +36 -0
- package/examples/config/minimal.toml +30 -0
- package/examples/config/profiles.toml +20 -0
- package/examples/config/runtime-appearance.toml +24 -0
- package/examples/config/sync-folder.toml +17 -0
- package/examples/config/tui-compatibility.toml +7 -0
- package/examples/config/with-plugins.toml +33 -0
- package/examples/plugins/hello.ts +17 -0
- package/examples/plugins/status-banner.ts +14 -0
- package/examples/plugins/theme.ts +32 -0
- package/examples/plugins/welcome-banner.ts +16 -0
- package/extra/linux/icons/hicolor/128x128/apps/fpasoterm.png +0 -0
- package/extra/linux/icons/hicolor/16x16/apps/fpasoterm.png +0 -0
- package/extra/linux/icons/hicolor/192x192/apps/fpasoterm.png +0 -0
- package/extra/linux/icons/hicolor/256x256/apps/fpasoterm.png +0 -0
- package/extra/linux/icons/hicolor/32x32/apps/fpasoterm.png +0 -0
- package/extra/linux/icons/hicolor/48x48/apps/fpasoterm.png +0 -0
- package/extra/linux/icons/hicolor/512x512/apps/fpasoterm.png +0 -0
- package/extra/linux/icons/hicolor/64x64/apps/fpasoterm.png +0 -0
- package/extra/linux/io.github.oyoguhito.fpasoterm.desktop +10 -0
- package/extra/logo/fpasoterm.png +0 -0
- package/extra/macos/fpasoterm.icns +0 -0
- package/extra/windows/fpasoterm.cmd +40 -0
- package/extra/windows/fpasoterm.ico +0 -0
- package/package.json +81 -0
- package/scripts/build-artifacts.js +183 -0
- package/scripts/generate-icon.js +251 -0
- package/scripts/init-jj-empty-main +41 -0
- package/scripts/install-linux-desktop.js +238 -0
- package/scripts/run +16 -0
- package/scripts/security/scan-secrets.js +89 -0
- package/scripts/tests/smoke.js +2476 -0
- package/scripts/uninstall-desktop.js +20 -0
- package/scripts/uninstall-linux-desktop.js +96 -0
- package/scripts/uninstall-windows-path.js +94 -0
- package/src/config.js +855 -0
- package/src/renderer/confirm.html +71 -0
- package/src/renderer/index.html +223 -0
- package/src/renderer/renderer.js +4166 -0
- package/src/renderer/styles.css +969 -0
- package/src/renderer/vendor/addon-fit/addon-fit.js +2 -0
- package/src/renderer/vendor/addon-image/LICENSE +19 -0
- package/src/renderer/vendor/addon-image/addon-image.js +3 -0
- package/src/renderer/vendor/addon-web-links/LICENSE +19 -0
- package/src/renderer/vendor/addon-web-links/addon-web-links.js +2 -0
- package/src/renderer/vendor/xterm/xterm.css +292 -0
- package/src/renderer/vendor/xterm/xterm.js +2 -0
- package/src-tauri/Cargo.lock +5253 -0
- package/src-tauri/Cargo.toml +29 -0
- package/src-tauri/build.rs +140 -0
- package/src-tauri/capabilities/default.json +13 -0
- package/src-tauri/default-config.toml +128 -0
- package/src-tauri/src/main.rs +9347 -0
- package/src-tauri/tauri.conf.json +60 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Default appearance config.
|
|
2
|
+
# Apply from a running fpasoterm terminal with a POSIX shell:
|
|
3
|
+
# printf '\033]777;config=/path/to/fpasoterm/examples/config/default-appearance.toml\a\r\n'
|
|
4
|
+
# On Windows, use examples/apply-default-appearance.ps1 or .bat.
|
|
5
|
+
|
|
6
|
+
[window]
|
|
7
|
+
title = "fpasoterm"
|
|
8
|
+
titlebarColor = "#1565c0"
|
|
9
|
+
|
|
10
|
+
[terminal]
|
|
11
|
+
lineHeight = 1
|
|
12
|
+
# Preserve application-selected ANSI/RGB colors and block/box glyph art.
|
|
13
|
+
minimumContrastRatio = 1
|
|
14
|
+
rescaleOverlappingGlyphs = false
|
|
15
|
+
backgroundOpacity = 0.65
|
|
16
|
+
|
|
17
|
+
[terminal.theme]
|
|
18
|
+
background = "rgba(16, 19, 23, 0.65)"
|
|
19
|
+
foreground = "#e8edf2"
|
|
20
|
+
cursor = "#f5d76e"
|
|
21
|
+
selectionBackground = "#35506b"
|
|
22
|
+
|
|
23
|
+
[keybindings]
|
|
24
|
+
prefix = "Mod+Shift"
|
|
25
|
+
logMenu = "L"
|
|
26
|
+
logToggle = "S"
|
|
27
|
+
logShow = "P"
|
|
28
|
+
copy = "C"
|
|
29
|
+
paste = "V"
|
|
30
|
+
menu = "M"
|
|
31
|
+
help = "H"
|
|
32
|
+
newWindow = "N"
|
|
33
|
+
broadcast = "B"
|
|
34
|
+
kill = "K"
|
|
35
|
+
tile = "T"
|
|
36
|
+
closeAll = "X"
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Minimal fpasoterm config example.
|
|
2
|
+
# Copy this to ~/.config/fpasoterm/User/config.toml and edit as needed.
|
|
3
|
+
|
|
4
|
+
[window]
|
|
5
|
+
title = "fpasoterm"
|
|
6
|
+
width = 1000
|
|
7
|
+
height = 680
|
|
8
|
+
titlebarColor = "#1565c0"
|
|
9
|
+
|
|
10
|
+
[terminal]
|
|
11
|
+
fontSize = 14
|
|
12
|
+
lineHeight = 1
|
|
13
|
+
minimumContrastRatio = 1
|
|
14
|
+
rescaleOverlappingGlyphs = false
|
|
15
|
+
backgroundOpacity = 0.65
|
|
16
|
+
fontFamily = "\"DejaVu Sans Mono\", \"Noto Sans Mono CJK JP\", \"Noto Sans CJK JP\", \"BIZ UDGothic\", \"Hiragino Sans\", Meiryo, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace"
|
|
17
|
+
termName = "xterm-256color"
|
|
18
|
+
# Keep UTF-8 unless a legacy program explicitly emits Shift_JIS or EUC-JP.
|
|
19
|
+
encoding = "utf-8"
|
|
20
|
+
# Leave empty for the platform default shell.
|
|
21
|
+
# Windows examples: "powershell.exe", "pwsh.exe", or "cmd.exe".
|
|
22
|
+
shell = ""
|
|
23
|
+
|
|
24
|
+
[keybindings]
|
|
25
|
+
prefix = "Mod+Shift"
|
|
26
|
+
newWindow = "N"
|
|
27
|
+
tile = "T"
|
|
28
|
+
|
|
29
|
+
[plugins]
|
|
30
|
+
enabled = []
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Apply this file with: fpasoterm --config ./examples/config/profiles.toml --profile large-font
|
|
2
|
+
|
|
3
|
+
[window]
|
|
4
|
+
title = "fpasoterm"
|
|
5
|
+
titlebarColor = "#1565c0"
|
|
6
|
+
|
|
7
|
+
[terminal]
|
|
8
|
+
fontSize = 14
|
|
9
|
+
backgroundOpacity = 0.65
|
|
10
|
+
|
|
11
|
+
# Profiles override normal config sections for one launch. They do not modify
|
|
12
|
+
# config.toml or User/window-state.json.
|
|
13
|
+
[profiles.large-font.terminal]
|
|
14
|
+
fontSize = 18
|
|
15
|
+
|
|
16
|
+
[profiles.transparent.window]
|
|
17
|
+
titlebarColor = "#00695c"
|
|
18
|
+
|
|
19
|
+
[profiles.transparent.terminal]
|
|
20
|
+
backgroundOpacity = 0.65
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Runtime appearance test config.
|
|
2
|
+
# Apply from a running fpasoterm terminal with a POSIX shell:
|
|
3
|
+
# printf '\033]777;config=/path/to/fpasoterm/examples/config/runtime-appearance.toml\a\r\n'
|
|
4
|
+
# On Windows, use examples/apply-runtime-appearance.ps1 or .bat.
|
|
5
|
+
|
|
6
|
+
[window]
|
|
7
|
+
title = "RUNTIME SAMPLE ACTIVE"
|
|
8
|
+
titlebarColor = "#d81b60"
|
|
9
|
+
|
|
10
|
+
# Uncomment these only when testing live window resizing.
|
|
11
|
+
# width = 1180
|
|
12
|
+
# height = 720
|
|
13
|
+
|
|
14
|
+
[terminal]
|
|
15
|
+
backgroundOpacity = 0.95
|
|
16
|
+
|
|
17
|
+
# Uncomment this only when testing live font resizing.
|
|
18
|
+
# fontSize = 18
|
|
19
|
+
|
|
20
|
+
[terminal.theme]
|
|
21
|
+
background = "#32004f"
|
|
22
|
+
foreground = "#fff176"
|
|
23
|
+
cursor = "#00e5ff"
|
|
24
|
+
selectionBackground = "#7b1fa2"
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Sync folder sample.
|
|
2
|
+
# Use a local folder that is already synchronized by Google Drive for desktop
|
|
3
|
+
# or another sync tool. fpasoterm does not call Google Drive APIs.
|
|
4
|
+
|
|
5
|
+
[sync]
|
|
6
|
+
enabled = true
|
|
7
|
+
provider = "folder"
|
|
8
|
+
path = "~/Google Drive/fpasoterm-sync"
|
|
9
|
+
channel = "default"
|
|
10
|
+
diagnostics = true
|
|
11
|
+
maxBytes = 1048576
|
|
12
|
+
|
|
13
|
+
[logging]
|
|
14
|
+
enabled = true
|
|
15
|
+
directory = "~/Google Drive/fpasoterm-sync/logs"
|
|
16
|
+
autoStart = false
|
|
17
|
+
maxBytes = 10485760
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# fpasoterm config example with TypeScript plugins enabled.
|
|
2
|
+
# The plugin paths are relative to ~/.config/fpasoterm/User/.
|
|
3
|
+
|
|
4
|
+
[window]
|
|
5
|
+
title = "fpasoterm plugins"
|
|
6
|
+
width = 1200
|
|
7
|
+
height = 760
|
|
8
|
+
titlebarColor = "#1565c0"
|
|
9
|
+
|
|
10
|
+
[terminal]
|
|
11
|
+
fontSize = 15
|
|
12
|
+
lineHeight = 1
|
|
13
|
+
minimumContrastRatio = 1
|
|
14
|
+
rescaleOverlappingGlyphs = false
|
|
15
|
+
backgroundOpacity = 0.65
|
|
16
|
+
scrollback = 3000
|
|
17
|
+
termName = "xterm-256color"
|
|
18
|
+
# Keep UTF-8 unless a legacy program explicitly emits Shift_JIS or EUC-JP.
|
|
19
|
+
encoding = "utf-8"
|
|
20
|
+
# Leave empty for the platform default shell.
|
|
21
|
+
# Windows examples: "powershell.exe", "pwsh.exe", or "cmd.exe".
|
|
22
|
+
shell = ""
|
|
23
|
+
|
|
24
|
+
[terminal.theme]
|
|
25
|
+
background = "rgba(16, 19, 23, 0.65)"
|
|
26
|
+
foreground = "#e8edf2"
|
|
27
|
+
cursor = "#f5d76e"
|
|
28
|
+
|
|
29
|
+
[plugins]
|
|
30
|
+
enabled = [
|
|
31
|
+
"plugins/hello.ts",
|
|
32
|
+
"plugins/theme.ts",
|
|
33
|
+
]
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/// <reference path="../../docs/fpasoterm-plugin.d.ts" />
|
|
2
|
+
// @fpasoterm-plugin version: 1.0.0
|
|
3
|
+
// @fpasoterm-plugin description: Writes a confirmation after the terminal is ready.
|
|
4
|
+
|
|
5
|
+
// This sample demonstrates the minimum plugin shape.
|
|
6
|
+
// Wait for the PTY before writing, so shell initialization cannot erase it.
|
|
7
|
+
const api = window.fpasotermPluginApi;
|
|
8
|
+
|
|
9
|
+
api.log('hello.ts loaded');
|
|
10
|
+
api.registerCommand('hello.show', 'Show Hello Banner', () => {
|
|
11
|
+
api.terminal.writeln('[fpasoterm plugin] hello.ts loaded');
|
|
12
|
+
api.terminal.focus();
|
|
13
|
+
});
|
|
14
|
+
api.onReady(() => {
|
|
15
|
+
api.terminal.writeln('');
|
|
16
|
+
api.terminal.writeln('[fpasoterm plugin] hello.ts loaded');
|
|
17
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/// <reference path="../../docs/fpasoterm-plugin.d.ts" />
|
|
2
|
+
// @fpasoterm-plugin version: 1.0.0
|
|
3
|
+
// @fpasoterm-plugin description: Adds a Plugins menu command that prints terminal status.
|
|
4
|
+
|
|
5
|
+
// Registers a menu action that shows resolved settings after startup.
|
|
6
|
+
const api = window.fpasotermPluginApi;
|
|
7
|
+
const { width, height } = api.config.window;
|
|
8
|
+
const enabledCount = api.config.plugins.enabled.length;
|
|
9
|
+
|
|
10
|
+
api.log(`status-banner.ts loaded for ${width}x${height}, plugins=${enabledCount}`);
|
|
11
|
+
api.registerCommand('status-banner.show', 'Show Plugin Status', () => {
|
|
12
|
+
api.terminal.writeln(`[fpasoterm] Status: ${width}x${height}, enabled plugins: ${enabledCount}.`);
|
|
13
|
+
api.terminal.focus();
|
|
14
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/// <reference path="../../docs/fpasoterm-plugin.d.ts" />
|
|
2
|
+
// @fpasoterm-plugin version: 1.0.0
|
|
3
|
+
// @fpasoterm-plugin description: Applies the visible teal sample terminal palette.
|
|
4
|
+
|
|
5
|
+
// This sample applies a visibly different terminal palette after startup.
|
|
6
|
+
// Use config.toml for normal settings; use plugins for temporary behavior changes.
|
|
7
|
+
const api = window.fpasotermPluginApi;
|
|
8
|
+
|
|
9
|
+
function applyTealTheme() {
|
|
10
|
+
api.terminal.options.theme = {
|
|
11
|
+
...api.config.terminal.theme,
|
|
12
|
+
background: 'rgba(8, 42, 48, 0.86)',
|
|
13
|
+
foreground: '#d8f6f3',
|
|
14
|
+
cursor: '#ffdc73',
|
|
15
|
+
selectionBackground: '#246b73',
|
|
16
|
+
blue: '#75c9ff',
|
|
17
|
+
cyan: '#73e6dd',
|
|
18
|
+
green: '#a9df7d',
|
|
19
|
+
};
|
|
20
|
+
api.fitAddon.fit();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
api.log('theme.ts loaded: applying the teal sample palette');
|
|
24
|
+
api.registerCommand('theme.apply-teal', 'Apply Teal Theme', () => {
|
|
25
|
+
applyTealTheme();
|
|
26
|
+
api.terminal.writeln('[fpasoterm plugin] theme.ts applied the teal sample palette.');
|
|
27
|
+
api.terminal.focus();
|
|
28
|
+
});
|
|
29
|
+
applyTealTheme();
|
|
30
|
+
api.onReady(() => {
|
|
31
|
+
api.terminal.writeln('[fpasoterm plugin] theme.ts applied the teal sample palette.');
|
|
32
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/// <reference path="../../docs/fpasoterm-plugin.d.ts" />
|
|
2
|
+
// @fpasoterm-plugin version: 1.0.0
|
|
3
|
+
// @fpasoterm-plugin description: Displays a local welcome banner after startup.
|
|
4
|
+
|
|
5
|
+
// Shows a small, local-only startup message after the PTY is ready.
|
|
6
|
+
const api = window.fpasotermPluginApi;
|
|
7
|
+
|
|
8
|
+
api.log('welcome-banner.ts loaded');
|
|
9
|
+
api.registerCommand('welcome-banner.show', 'Show Welcome Banner', () => {
|
|
10
|
+
api.terminal.writeln(`[fpasoterm ${api.version}] Welcome banner plugin is active.`);
|
|
11
|
+
api.terminal.focus();
|
|
12
|
+
});
|
|
13
|
+
api.onReady(() => {
|
|
14
|
+
api.terminal.writeln('');
|
|
15
|
+
api.terminal.writeln(`[fpasoterm ${api.version}] Welcome banner plugin is active.`);
|
|
16
|
+
});
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
[Desktop Entry]
|
|
2
|
+
Type=Application
|
|
3
|
+
Name=fpasoterm
|
|
4
|
+
Comment=Cross-platform terminal with Japanese IME support
|
|
5
|
+
Exec=fpasoterm
|
|
6
|
+
Icon=io.github.oyoguhito.fpasoterm
|
|
7
|
+
Terminal=false
|
|
8
|
+
Categories=System;TerminalEmulator;
|
|
9
|
+
StartupNotify=true
|
|
10
|
+
StartupWMClass=fpasoterm
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
@echo off
|
|
2
|
+
setlocal DisableDelayedExpansion
|
|
3
|
+
set "FPASOTERM_ARGS=%*"
|
|
4
|
+
|
|
5
|
+
rem Console wrapper for the GUI-subsystem fpasoterm.exe beside this file.
|
|
6
|
+
rem CLI operations run as a direct child so output and exit codes return to the
|
|
7
|
+
rem invoking PowerShell/cmd console; normal launches remain detached.
|
|
8
|
+
set "FPASOTERM_EXE=%~dp0fpasoterm.exe"
|
|
9
|
+
if not exist "%FPASOTERM_EXE%" (
|
|
10
|
+
echo fpasoterm: executable not found: "%FPASOTERM_EXE%" 1>&2
|
|
11
|
+
exit /b 1
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
:scan
|
|
15
|
+
if "%~1"=="" goto run
|
|
16
|
+
for %%F in (
|
|
17
|
+
--help -h --version -v --update-check --doctor --list -l --close -q --show-config
|
|
18
|
+
--completion --completion-install --completion-uninstall
|
|
19
|
+
--profile-list --config-check --config-path --config-example
|
|
20
|
+
--diagnostics --open-log-dir --copy-diagnostics
|
|
21
|
+
--plugin-list --plugin-path --plugin-info --plugin-uninstall --plugin-search --plugin-install
|
|
22
|
+
--plugin-ports-dir --plugin-install-file
|
|
23
|
+
--force --enable
|
|
24
|
+
--enable-plugin --disable-plugin --plugin-enable --plugin-disable
|
|
25
|
+
--plugin-enable-all --plugin-disable-all
|
|
26
|
+
--reset-window-state -r --reset-config -R --update-config --prune-config
|
|
27
|
+
--setup-sync --foreground -F
|
|
28
|
+
--broadcast --broadcast-target --broadcast-sync
|
|
29
|
+
) do if /I "%~1"=="%%F" set "FPASOTERM_WAIT=1"
|
|
30
|
+
shift
|
|
31
|
+
goto scan
|
|
32
|
+
|
|
33
|
+
:run
|
|
34
|
+
if defined FPASOTERM_WAIT (
|
|
35
|
+
call "%FPASOTERM_EXE%" %FPASOTERM_ARGS%
|
|
36
|
+
exit /b %ERRORLEVEL%
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
start "" "%FPASOTERM_EXE%" %FPASOTERM_ARGS%
|
|
40
|
+
exit /b 0
|
|
Binary file
|
package/package.json
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "fpasoterm",
|
|
3
|
+
"version": "1.6.0",
|
|
4
|
+
"description": "Cross-platform terminal with Japanese IME support.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"homepage": "https://github.com/oyoguhito/fpasoterm#readme",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/oyoguhito/fpasoterm.git"
|
|
10
|
+
},
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/oyoguhito/fpasoterm/issues"
|
|
13
|
+
},
|
|
14
|
+
"publishConfig": {
|
|
15
|
+
"access": "public"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"terminal",
|
|
19
|
+
"xterm",
|
|
20
|
+
"ime",
|
|
21
|
+
"japanese",
|
|
22
|
+
"chromeos"
|
|
23
|
+
],
|
|
24
|
+
"bin": {
|
|
25
|
+
"fpasoterm": "bin/fpasoterm"
|
|
26
|
+
},
|
|
27
|
+
"files": [
|
|
28
|
+
"bin/",
|
|
29
|
+
"completions/",
|
|
30
|
+
"docs/",
|
|
31
|
+
"examples/",
|
|
32
|
+
"extra/",
|
|
33
|
+
"scripts/",
|
|
34
|
+
"src/",
|
|
35
|
+
"src-tauri/Cargo.lock",
|
|
36
|
+
"src-tauri/Cargo.toml",
|
|
37
|
+
"src-tauri/build.rs",
|
|
38
|
+
"src-tauri/capabilities/",
|
|
39
|
+
"src-tauri/default-config.toml",
|
|
40
|
+
"src-tauri/src/",
|
|
41
|
+
"src-tauri/tauri.conf.json",
|
|
42
|
+
"CHANGELOG.md",
|
|
43
|
+
"CONTRIBUTING.md",
|
|
44
|
+
"INSTALL.md",
|
|
45
|
+
"INSTALL.ja.md",
|
|
46
|
+
"README.md",
|
|
47
|
+
"README.ja.md",
|
|
48
|
+
"LICENSE",
|
|
49
|
+
"package.json",
|
|
50
|
+
"package-lock.json"
|
|
51
|
+
],
|
|
52
|
+
"scripts": {
|
|
53
|
+
"start": "node ./bin/fpasoterm",
|
|
54
|
+
"tauri": "tauri",
|
|
55
|
+
"dev": "tauri dev",
|
|
56
|
+
"build": "tauri build",
|
|
57
|
+
"check": "npm run check:syntax && npm test && cargo check --manifest-path src-tauri/Cargo.toml",
|
|
58
|
+
"check:syntax": "node --check bin/fpasoterm && node --check scripts/uninstall-desktop.js && node --check scripts/uninstall-windows-path.js && node --check src/config.js && node --check src/renderer/renderer.js",
|
|
59
|
+
"test": "node scripts/tests/smoke.js",
|
|
60
|
+
"scan:secrets": "node scripts/security/scan-secrets.js",
|
|
61
|
+
"security": "npm run scan:secrets && npm run audit:prod",
|
|
62
|
+
"audit:prod": "npm audit --omit=dev",
|
|
63
|
+
"generate:icons": "node scripts/generate-icon.js",
|
|
64
|
+
"install:desktop": "node scripts/install-linux-desktop.js",
|
|
65
|
+
"update:desktop": "node scripts/install-linux-desktop.js",
|
|
66
|
+
"uninstall:desktop": "node scripts/uninstall-desktop.js",
|
|
67
|
+
"build:artifacts": "node scripts/build-artifacts.js",
|
|
68
|
+
"build:bundles": "node scripts/build-artifacts.js --bundles-only"
|
|
69
|
+
},
|
|
70
|
+
"dependencies": {
|
|
71
|
+
"@tauri-apps/api": "^2.11.1",
|
|
72
|
+
"@tauri-apps/cli": "^2.11.4",
|
|
73
|
+
"@tauri-apps/plugin-notification": "^2.3.3",
|
|
74
|
+
"@xterm/addon-fit": "0.12.0-beta.288",
|
|
75
|
+
"@xterm/addon-image": "0.10.0-beta.288",
|
|
76
|
+
"@xterm/addon-web-links": "0.12.0",
|
|
77
|
+
"@xterm/xterm": "6.1.0-beta.288",
|
|
78
|
+
"smol-toml": "^1.4.2",
|
|
79
|
+
"typescript": "^5.9.3"
|
|
80
|
+
}
|
|
81
|
+
}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
const childProcess = require('node:child_process');
|
|
2
|
+
const fs = require('node:fs');
|
|
3
|
+
const path = require('node:path');
|
|
4
|
+
|
|
5
|
+
const root = path.resolve(__dirname, '..');
|
|
6
|
+
const artifactsDir = path.join(root, 'artifacts');
|
|
7
|
+
const npmCacheDir = path.join(artifactsDir, '.npm-cache');
|
|
8
|
+
const packageJson = require(path.join(root, 'package.json'));
|
|
9
|
+
const version = packageJson.version;
|
|
10
|
+
const args = new Set(process.argv.slice(2));
|
|
11
|
+
const sourceOnly = args.has('--source-only');
|
|
12
|
+
const bundlesOnly = args.has('--bundles-only');
|
|
13
|
+
const artifactLabel = process.env.FPASOTERM_ARTIFACT_LABEL || '';
|
|
14
|
+
if (sourceOnly && bundlesOnly) {
|
|
15
|
+
throw new Error('Use only one of --source-only or --bundles-only');
|
|
16
|
+
}
|
|
17
|
+
const packageEntries = [
|
|
18
|
+
'bin',
|
|
19
|
+
'docs',
|
|
20
|
+
'examples',
|
|
21
|
+
'extra',
|
|
22
|
+
'scripts',
|
|
23
|
+
'src',
|
|
24
|
+
'src-tauri',
|
|
25
|
+
'CHANGELOG.md',
|
|
26
|
+
'CONTRIBUTING.md',
|
|
27
|
+
'INSTALL.md',
|
|
28
|
+
'README.md',
|
|
29
|
+
'LICENSE',
|
|
30
|
+
'package.json',
|
|
31
|
+
'package-lock.json',
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
// Resolves npm through its JavaScript entry point when available. This avoids
|
|
35
|
+
// invoking npm.cmd through a shell on Windows, which Node deprecates (DEP0190).
|
|
36
|
+
function npmInvocation(args) {
|
|
37
|
+
const bundledNpmCli = path.join(path.dirname(process.execPath), 'node_modules', 'npm', 'bin', 'npm-cli.js');
|
|
38
|
+
const npmCli = [process.env.npm_execpath, bundledNpmCli].find((candidate) => candidate && fs.existsSync(candidate));
|
|
39
|
+
if (npmCli) {
|
|
40
|
+
return { command: process.execPath, args: [npmCli, ...args] };
|
|
41
|
+
}
|
|
42
|
+
return { command: process.platform === 'win32' ? 'npm.cmd' : 'npm', args };
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Runs packaging commands from the repository root with an artifact-local npm cache.
|
|
46
|
+
function run(command, args, options = {}) {
|
|
47
|
+
const invocation = command === 'npm' ? npmInvocation(args) : { command, args };
|
|
48
|
+
const result = childProcess.spawnSync(invocation.command, invocation.args, {
|
|
49
|
+
cwd: root,
|
|
50
|
+
stdio: 'inherit',
|
|
51
|
+
env: {
|
|
52
|
+
...process.env,
|
|
53
|
+
npm_config_cache: npmCacheDir,
|
|
54
|
+
npm_config_audit: 'false',
|
|
55
|
+
npm_config_fund: 'false',
|
|
56
|
+
npm_config_update_notifier: 'false',
|
|
57
|
+
NO_UPDATE_NOTIFIER: '1',
|
|
58
|
+
},
|
|
59
|
+
...options,
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
if (result.error) {
|
|
63
|
+
throw result.error;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (result.status !== 0) {
|
|
67
|
+
throw new Error(`${command} ${args.join(' ')} exited with status ${result.status}`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Copies source entries while excluding generated or dependency directories.
|
|
72
|
+
function copyEntry(entry, targetRoot) {
|
|
73
|
+
fs.cpSync(path.join(root, entry), path.join(targetRoot, entry), {
|
|
74
|
+
recursive: true,
|
|
75
|
+
filter: (source) => {
|
|
76
|
+
const relative = path.relative(root, source).replaceAll('\\', '/');
|
|
77
|
+
return ![
|
|
78
|
+
'artifacts',
|
|
79
|
+
'node_modules',
|
|
80
|
+
'src-tauri/target',
|
|
81
|
+
].some((ignored) => relative === ignored || relative.startsWith(`${ignored}/`));
|
|
82
|
+
},
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Adds the CI platform label to release assets so macOS/Windows bundle names do
|
|
87
|
+
// not collide when every matrix artifact is uploaded to the same GitHub Release.
|
|
88
|
+
function labelArtifactName(fileName) {
|
|
89
|
+
if (!artifactLabel) {
|
|
90
|
+
return fileName;
|
|
91
|
+
}
|
|
92
|
+
const parsed = path.parse(fileName);
|
|
93
|
+
return `${parsed.name}-${artifactLabel}${parsed.ext}`;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Places a console-subsystem wrapper next to the Windows GUI executable. It
|
|
97
|
+
// waits for CLI-only operations so PowerShell redraws its prompt on completion.
|
|
98
|
+
function copyWindowsCommandWrapper() {
|
|
99
|
+
if (process.platform !== 'win32') {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
const wrapper = path.join(root, 'extra', 'windows', 'fpasoterm.cmd');
|
|
103
|
+
const releaseDir = path.join(root, 'src-tauri', 'target', 'release');
|
|
104
|
+
if (!fs.existsSync(wrapper) || !fs.existsSync(path.join(releaseDir, 'fpasoterm.exe'))) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
fs.copyFileSync(wrapper, path.join(releaseDir, 'fpasoterm.cmd'));
|
|
108
|
+
fs.copyFileSync(wrapper, path.join(artifactsDir, labelArtifactName(`fpasoterm-${version}-windows-cli.cmd`)));
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
fs.rmSync(artifactsDir, { recursive: true, force: true });
|
|
112
|
+
fs.mkdirSync(artifactsDir, { recursive: true });
|
|
113
|
+
|
|
114
|
+
if (!bundlesOnly) {
|
|
115
|
+
const npmPackageRoot = path.join(artifactsDir, 'package');
|
|
116
|
+
fs.mkdirSync(npmPackageRoot, { recursive: true });
|
|
117
|
+
for (const entry of packageEntries) {
|
|
118
|
+
copyEntry(entry, npmPackageRoot);
|
|
119
|
+
}
|
|
120
|
+
run('tar', ['-czf', `fpasoterm-${version}.tgz`, 'package'], {
|
|
121
|
+
cwd: artifactsDir,
|
|
122
|
+
});
|
|
123
|
+
fs.rmSync(npmPackageRoot, { recursive: true, force: true });
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (!sourceOnly) {
|
|
127
|
+
const buildArgs = ['run', 'build'];
|
|
128
|
+
if (process.platform === 'linux') {
|
|
129
|
+
// AppImage bundling is unstable in some ChromeOS/Baguette and CI
|
|
130
|
+
// environments. Build the Linux package formats that are currently
|
|
131
|
+
// reproducible, and keep the source archives platform-independent.
|
|
132
|
+
buildArgs.push('--', '--bundles', 'deb,rpm');
|
|
133
|
+
}
|
|
134
|
+
run('npm', buildArgs);
|
|
135
|
+
copyWindowsCommandWrapper();
|
|
136
|
+
|
|
137
|
+
const bundleDir = path.join(root, 'src-tauri', 'target', 'release', 'bundle');
|
|
138
|
+
if (fs.existsSync(bundleDir)) {
|
|
139
|
+
const copyBundles = (directory) => {
|
|
140
|
+
for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {
|
|
141
|
+
const entryPath = path.join(directory, entry.name);
|
|
142
|
+
if (entry.isDirectory()) {
|
|
143
|
+
if (entry.name.endsWith('.app')) {
|
|
144
|
+
const appArchive = `${entry.name.replace(/\.app$/, '')}-${version}-${artifactLabel || process.arch}.app.tar.gz`;
|
|
145
|
+
run('tar', ['-czf', path.join(artifactsDir, appArchive), entry.name], {
|
|
146
|
+
cwd: directory,
|
|
147
|
+
});
|
|
148
|
+
} else {
|
|
149
|
+
copyBundles(entryPath);
|
|
150
|
+
}
|
|
151
|
+
} else if (
|
|
152
|
+
entry.isFile()
|
|
153
|
+
&& ['.deb', '.rpm', '.dmg', '.msi', '.exe'].includes(path.extname(entry.name))
|
|
154
|
+
&& entry.name.includes(version)
|
|
155
|
+
) {
|
|
156
|
+
fs.copyFileSync(entryPath, path.join(artifactsDir, labelArtifactName(entry.name)));
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
copyBundles(bundleDir);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
let portableRoot;
|
|
165
|
+
if (!bundlesOnly) {
|
|
166
|
+
const portableName = `fpasoterm-${version}-source-portable`;
|
|
167
|
+
portableRoot = path.join(artifactsDir, portableName);
|
|
168
|
+
fs.mkdirSync(portableRoot, { recursive: true });
|
|
169
|
+
|
|
170
|
+
for (const entry of packageEntries) {
|
|
171
|
+
copyEntry(entry, portableRoot);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
run('tar', ['-czf', `${portableName}.tar.gz`, portableName], {
|
|
175
|
+
cwd: artifactsDir,
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if (portableRoot) {
|
|
180
|
+
fs.rmSync(portableRoot, { recursive: true, force: true });
|
|
181
|
+
}
|
|
182
|
+
fs.rmSync(npmCacheDir, { recursive: true, force: true });
|
|
183
|
+
console.log(`Artifacts written to ${artifactsDir}`);
|