This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
node_modules/
|
||||
dist/
|
||||
build/artifacts/
|
||||
releases/
|
||||
*.log
|
||||
.tmp/
|
||||
tests/.tmp/
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
# Getting Started
|
||||
|
||||
StepForge is a fully offline desktop app. Nothing is uploaded or synced, and
|
||||
all guides stay on your machine.
|
||||
|
||||
## 1. Install
|
||||
|
||||
From the repository root:
|
||||
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
That installs Electron and the local packaging tools used by the scripts.
|
||||
|
||||
## 2. Launch the app
|
||||
|
||||
```bash
|
||||
npm start
|
||||
```
|
||||
|
||||
The first launch creates the local StepForge data directory. On Linux it is
|
||||
usually under `~/.local/share/stepforge`. On Windows it is usually under
|
||||
`%APPDATA%/stepforge`.
|
||||
|
||||
## 3. Create your first guide
|
||||
|
||||
In the library view:
|
||||
|
||||
1. Click `New guide`.
|
||||
2. Give the guide a clear title.
|
||||
3. Open the guide to enter the editor.
|
||||
|
||||
You can also import a guide archive with `Import archive` if you already have
|
||||
one.
|
||||
|
||||
## 4. Add content
|
||||
|
||||
There are two simple ways to start:
|
||||
|
||||
1. Import screenshots with the `Import` button in the editor.
|
||||
2. Paste an image from the clipboard if you already copied one.
|
||||
|
||||
If you want to capture new screenshots, open `Quick` actions and start a
|
||||
capture session. Use `Settings` to set the capture hotkey and other capture
|
||||
options.
|
||||
|
||||
## 5. Edit the guide
|
||||
|
||||
The editor is split into three panes:
|
||||
|
||||
1. Steps on the left
|
||||
2. Canvas in the center
|
||||
3. Properties on the right
|
||||
|
||||
Use the canvas tools to add shapes, arrows, text, blur, highlight, numbers,
|
||||
and crops. Use the right pane to edit the step title, description, and
|
||||
annotation details.
|
||||
|
||||
## 6. Save and export
|
||||
|
||||
Use these actions from the top bar:
|
||||
|
||||
1. `Save` writes the guide to disk.
|
||||
2. `Export` opens format choices such as JSON, Markdown, HTML, PDF, GIF,
|
||||
image bundle, DOCX, and PPTX.
|
||||
3. `Linked` shows archive details when a guide is linked to a shared `.sfgz`
|
||||
file.
|
||||
|
||||
If you want to find commands quickly, press `Ctrl+/` for Quick Actions.
|
||||
|
||||
## Useful shortcuts
|
||||
|
||||
1. `Ctrl+/` opens Quick Actions
|
||||
2. `Ctrl+S` saves the current guide
|
||||
3. `Ctrl+Z` undoes the last edit
|
||||
4. `Ctrl+Shift+Z` redoes the last edit
|
||||
5. `Alt+Up` and `Alt+Down` move the selected step
|
||||
|
||||
## If something is missing
|
||||
|
||||
1. Open `Settings` to review capture, export, and editor options.
|
||||
2. Run `npm run sample` to generate a sample guide and exported examples.
|
||||
3. Run `bash scripts/verify.sh` to check the full offline workflow.
|
||||
|
||||
## Optional builds
|
||||
|
||||
1. `bash scripts/build-release.sh` assembles the offline release layout.
|
||||
2. `npm run package:windows` creates the portable Windows `.exe` in
|
||||
`releases/`.
|
||||
3. `bash scripts/package-linux.sh` creates Linux release artifacts.
|
||||
@@ -71,6 +71,8 @@ using only Node built-ins.
|
||||
|
||||
## Getting Started
|
||||
|
||||
For a shorter walkthrough, see [GETTING_STARTED.md](GETTING_STARTED.md).
|
||||
|
||||
Requirements: Node.js 20+ and npm (Electron is the only dependency).
|
||||
|
||||
```bash
|
||||
@@ -102,7 +104,8 @@ bash scripts/bootstrap-offline.sh # verify toolchain availability
|
||||
bash scripts/verify.sh # full test suite + smoke checks
|
||||
bash scripts/build-release.sh # assemble runnable app directory
|
||||
bash scripts/package-linux.sh # portable tar.gz + .deb (+ AppDir spec)
|
||||
pwsh scripts/package-windows.ps1 # portable zip + installer specs
|
||||
npm run package:windows # portable Windows .exe in releases/
|
||||
pwsh scripts/package-windows.ps1 # same Windows portable build via PowerShell
|
||||
```
|
||||
|
||||
See [build/build_report.md](build/build_report.md) for what was produced on
|
||||
|
||||
Generated
+3185
-9
File diff suppressed because it is too large
Load Diff
+4
-1
@@ -3,17 +3,20 @@
|
||||
"version": "0.1.0",
|
||||
"description": "Fully offline desktop tool for capturing, annotating, and exporting step-by-step guides.",
|
||||
"main": "app/main.js",
|
||||
"author": "StepForge tyler@twestbrook.com",
|
||||
"license": "MPL-2.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "node scripts/start-electron.js",
|
||||
"test": "node --test tests/unit/",
|
||||
"sample": "node scripts/make-sample-guide.js",
|
||||
"package:windows": "node scripts/package-windows.js",
|
||||
"build": "bash scripts/build-release.sh",
|
||||
"verify": "bash scripts/verify.sh",
|
||||
"bootstrap": "bash scripts/bootstrap-offline.sh"
|
||||
},
|
||||
"devDependencies": {
|
||||
"electron": "^41.7.1"
|
||||
"electron": "^41.7.1",
|
||||
"electron-builder": "^26.15.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
#!/usr/bin/env node
|
||||
'use strict';
|
||||
|
||||
const fs = require('node:fs');
|
||||
const os = require('node:os');
|
||||
const path = require('node:path');
|
||||
|
||||
const { build, Platform } = require('electron-builder');
|
||||
|
||||
const ROOT_DIR = path.resolve(__dirname, '..');
|
||||
const PACKAGE_JSON = require(path.join(ROOT_DIR, 'package.json'));
|
||||
const RELEASE_DIR = path.resolve(process.env.STEPFORGE_RELEASE_DIR || path.join(ROOT_DIR, 'releases'));
|
||||
const WORK_DIR = fs.mkdtempSync(path.join(os.tmpdir(), 'stepforge-win-'));
|
||||
const OUTPUT_DIR = path.join(WORK_DIR, 'output');
|
||||
const ARTIFACT_NAME = 'stepforge-windows-x64-portable.exe';
|
||||
|
||||
function findPortableExe(dir) {
|
||||
if (!fs.existsSync(dir)) return null;
|
||||
const stack = [dir];
|
||||
while (stack.length) {
|
||||
const current = stack.pop();
|
||||
for (const entry of fs.readdirSync(current, { withFileTypes: true })) {
|
||||
const abs = path.join(current, entry.name);
|
||||
if (entry.isDirectory()) {
|
||||
stack.push(abs);
|
||||
continue;
|
||||
}
|
||||
if (entry.isFile() && entry.name.toLowerCase().endsWith('.exe')) return abs;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
async function main() {
|
||||
fs.mkdirSync(RELEASE_DIR, { recursive: true });
|
||||
fs.rmSync(OUTPUT_DIR, { recursive: true, force: true });
|
||||
|
||||
const config = {
|
||||
appId: 'com.stepforge.app',
|
||||
productName: 'StepForge',
|
||||
directories: {
|
||||
output: OUTPUT_DIR,
|
||||
},
|
||||
files: [
|
||||
'app/**/*',
|
||||
'core/**/*',
|
||||
'exporters/**/*',
|
||||
'package.json',
|
||||
],
|
||||
asar: true,
|
||||
compression: 'normal',
|
||||
artifactName: ARTIFACT_NAME,
|
||||
win: {
|
||||
target: ['portable'],
|
||||
},
|
||||
};
|
||||
|
||||
try {
|
||||
await build({
|
||||
targets: Platform.WINDOWS.createTarget('portable'),
|
||||
config,
|
||||
});
|
||||
} catch (err) {
|
||||
throw new Error(`Windows portable build failed: ${err.message}`);
|
||||
}
|
||||
|
||||
const builtExe = findPortableExe(OUTPUT_DIR);
|
||||
if (!builtExe) {
|
||||
throw new Error(`No .exe artifact was produced in ${OUTPUT_DIR}`);
|
||||
}
|
||||
|
||||
const releaseExe = path.join(RELEASE_DIR, path.basename(builtExe));
|
||||
fs.copyFileSync(builtExe, releaseExe);
|
||||
|
||||
console.log(`StepForge ${PACKAGE_JSON.version} Windows portable build written to ${releaseExe}`);
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(err.message || err);
|
||||
process.exitCode = 1;
|
||||
});
|
||||
@@ -0,0 +1,5 @@
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
$Root = Split-Path -Parent $PSScriptRoot
|
||||
node (Join-Path $Root 'scripts/package-windows.js') @args
|
||||
exit $LASTEXITCODE
|
||||
Reference in New Issue
Block a user