Scaffold StepForge: docs, license, audit, npm project
- Environment audit and stack decision in build/agent_audit.md (Node + Electron shell over dependency-free core; deviation recorded) - Rewrite README/ARCHITECTURE/CONTRIBUTING for StepForge - Add SECURITY.md threat model, CODE_OF_CONDUCT.md, CHANGELOG.md, MPL-2.0 - Replace template grep checks with structural workflow check Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,7 @@
|
|||||||
|
node_modules/
|
||||||
|
dist/
|
||||||
|
build/artifacts/
|
||||||
|
*.log
|
||||||
|
.tmp/
|
||||||
|
tests/.tmp/
|
||||||
|
examples/.tmp/
|
||||||
+115
-7
@@ -1,14 +1,122 @@
|
|||||||
# Architecture
|
# Architecture
|
||||||
|
|
||||||
This template is organized around three small areas:
|
StepForge is split into a **dependency-free Node.js core** and a thin
|
||||||
|
**Electron desktop shell**. All product logic lives in `core/` and
|
||||||
|
`exporters/` and runs (and is tested) headlessly with plain `node`. The shell
|
||||||
|
in `app/` only provides the window, the canvas UI, screen capture, hotkeys,
|
||||||
|
and the clipboard.
|
||||||
|
|
||||||
- Repository guidance in `README.md` and `CONTRIBUTING.md`.
|
## Repository Layout
|
||||||
- User-facing templates in `.github/`.
|
|
||||||
- Validation and automation in `tests/` and `.gitea/workflows/`.
|
```text
|
||||||
|
app/ Electron shell: main process, preload bridge, renderer UI
|
||||||
|
core/ Dependency-free domain logic (schema, store, archive, search,
|
||||||
|
placeholders, render AST, png/gif/pdf/zip primitives, locks,
|
||||||
|
snapshots, settings)
|
||||||
|
exporters/ One module per output format, all consuming the Render AST
|
||||||
|
scripts/ bootstrap / verify / build / package scripts (sh + ps1)
|
||||||
|
tests/
|
||||||
|
run_test.sh entrypoint — runs every tests/checks/test_*.sh
|
||||||
|
checks/ shell wrappers that invoke the node test suites
|
||||||
|
unit/ node:test workflow suites
|
||||||
|
fixtures/ test images and guides
|
||||||
|
examples/ sample guide + sample exports
|
||||||
|
assets/ app icon and packaged static assets
|
||||||
|
build/ agent_audit.md, build_report.md, artifacts_manifest.json
|
||||||
|
docs/ file-format and data-model documentation
|
||||||
|
vendor/ reserved for vendored deps (reuse only; nothing fetched)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Data Model
|
||||||
|
|
||||||
|
Internal working storage is **folder-based**; sharing/backups use a
|
||||||
|
**single-file zip archive** (`.sfgz`).
|
||||||
|
|
||||||
|
```text
|
||||||
|
<data root>/ (~/.local/share/stepforge, %APPDATA%/stepforge,
|
||||||
|
settings/ or $STEPFORGE_DATA_DIR)
|
||||||
|
app-settings.json
|
||||||
|
placeholders.json global placeholders
|
||||||
|
templates/<format>/<name>.template.json
|
||||||
|
library/
|
||||||
|
folders.json folder tree + guide->folder mapping
|
||||||
|
guides/<guide-id>/
|
||||||
|
guide.json guide metadata (schema below)
|
||||||
|
steps/<step-id>/
|
||||||
|
step.json
|
||||||
|
original.png never mutated after capture
|
||||||
|
working.png crop target; annotations stay vector JSON
|
||||||
|
history/snapshots/*.zip automated + manual backups
|
||||||
|
index/search-index.json inverted full-text index
|
||||||
|
temp/ previews; cleaned on close
|
||||||
|
shared-links/ linked-guide registry
|
||||||
|
```
|
||||||
|
|
||||||
|
- `guide.json` — schemaVersion, guideId, title, descriptionHtml,
|
||||||
|
placeholders, flags (focusedViewDefault, ...), stepsOrder, favorite,
|
||||||
|
linkedSource, exportProfiles, createdAt/updatedAt.
|
||||||
|
- `step.json` — stepId, parentStepId, kind (`image | empty | content`),
|
||||||
|
status (`todo | in-progress | done`), title, descriptionHtml, hidden,
|
||||||
|
skipped, focusedView {enabled, zoom, panX, panY}, image paths + size,
|
||||||
|
`annotations[]` (normalized scene graph, coordinates in 0..1 fractions of
|
||||||
|
the image), textBlocks[], codeBlocks[], tableBlocks[], links[].
|
||||||
|
|
||||||
|
All writes are **atomic** (write to `*.tmp`, fsync, rename). Deleting a guide
|
||||||
|
moves it to `library/trash/` first.
|
||||||
|
|
||||||
|
## Annotation Scene Graph
|
||||||
|
|
||||||
|
Annotations are stored as normalized JSON, never as an editor-library blob.
|
||||||
|
Coordinates are fractions of the image (resolution-independent). Types:
|
||||||
|
`rect, oval, line, arrow, text, tooltip, number, blur, highlight, magnify,
|
||||||
|
cursor`. The same geometry is rendered by the editor canvas (HTML5 canvas)
|
||||||
|
and by the export rasterizer (`core/raster.js`), so what you see is what
|
||||||
|
exports.
|
||||||
|
|
||||||
|
## Render Pipeline
|
||||||
|
|
||||||
|
```text
|
||||||
|
guide.json + step.json + settings
|
||||||
|
│ core/renderast.js (placeholder expansion, numbering, filtering
|
||||||
|
▼ hidden/skipped, focused-view geometry)
|
||||||
|
Render AST ──► exporters/json.js .json + steps-<title>/ images
|
||||||
|
──► exporters/markdown.js .md + steps-<title>/ images
|
||||||
|
──► exporters/html-simple.js single self-contained .html
|
||||||
|
──► exporters/html-rich.js checkboxes + floating TOC
|
||||||
|
──► exporters/pdf.js native PDF writer (core/pdf.js)
|
||||||
|
──► exporters/gif.js GIF89a encoder (core/gif.js)
|
||||||
|
──► exporters/image-bundle.js annotated PNGs + metadata
|
||||||
|
──► exporters/docx.js zip+XML (core/zip.js)
|
||||||
|
──► exporters/pptx.js zip+XML (core/zip.js)
|
||||||
|
```
|
||||||
|
|
||||||
|
Image-bearing exporters rasterize annotations with `core/raster.js` on top of
|
||||||
|
PNG pixels decoded by `core/png.js`. Every exporter accepts a template object
|
||||||
|
(per-format settings persisted under `settings/templates/`, shareable as
|
||||||
|
`.sfglt` zip files).
|
||||||
|
|
||||||
|
## Shell / Core Boundary
|
||||||
|
|
||||||
|
The renderer never touches the filesystem. `app/preload.js` exposes a typed
|
||||||
|
IPC API (`stepforge.*`), and `app/main.js` routes calls into `core/`. Screen
|
||||||
|
capture uses Electron's `desktopCapturer` (full screen, window) and an
|
||||||
|
overlay window for region selection; hotkeys use `globalShortcut`.
|
||||||
|
|
||||||
|
## Security Rules
|
||||||
|
|
||||||
|
- Zero network code paths: no sockets, no telemetry, no update or license
|
||||||
|
checks, no remote fonts in exports.
|
||||||
|
- Archive imports validate every entry name against path traversal and
|
||||||
|
absolute paths before extraction (`core/zip.js`).
|
||||||
|
- Linked guides use sidecar `*.lock-sfgz` lock files; conflicts surface a
|
||||||
|
keep-editing / discard dialog and last-write-wins is documented.
|
||||||
|
- Renderer runs with `contextIsolation: true`, `nodeIntegration: false`,
|
||||||
|
and `sandbox` enabled; only the preload API is exposed.
|
||||||
|
|
||||||
## Workflow
|
## Workflow
|
||||||
|
|
||||||
1. Update the documentation and templates.
|
1. Change core/exporter logic together with its workflow tests in
|
||||||
2. Put shell checks in `tests/checks/`.
|
`tests/unit/`.
|
||||||
|
2. Put shell checks in `tests/checks/` so the shared runner picks them up.
|
||||||
3. Run `bash tests/run_test.sh` locally.
|
3. Run `bash tests/run_test.sh` locally.
|
||||||
4. Open a pull request so Gitea Actions can verify the template on PR open.
|
4. Open a pull request so CI can verify on PR open.
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
All notable user-visible changes are recorded here. The format follows
|
||||||
|
Keep-a-Changelog conventions; versions follow semver.
|
||||||
|
|
||||||
|
## [0.1.0] - 2026-06-10
|
||||||
|
|
||||||
|
Initial release.
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Guide library with folders, favorites, title + full-text search, and a
|
||||||
|
quick-actions palette.
|
||||||
|
- Capture engine: full-screen / active-window / region capture, delay,
|
||||||
|
pause/resume, global hotkeys, click markers, clipboard paste, image import.
|
||||||
|
- Three-pane editor: step tree with substeps, statuses, hidden/skipped steps,
|
||||||
|
focused view, autosave, undo/redo.
|
||||||
|
- Annotation canvas: rect, oval, line, arrow, text, tooltip, numbered marker,
|
||||||
|
blur, highlight, magnify, crop; normalized JSON scene graph.
|
||||||
|
- Rich text descriptions, informational text blocks, code blocks, tables,
|
||||||
|
step links, and placeholders (global / guide / system scope).
|
||||||
|
- Single-file `.sfgz` share archives, linked guides with lock files,
|
||||||
|
snapshot backups and restore.
|
||||||
|
- Exporters: JSON, Markdown, Simple HTML, Rich HTML, PDF, animated GIF,
|
||||||
|
image bundle, DOCX, PPTX; per-format templates shareable as `.sfglt`.
|
||||||
|
- System/light/dark theming, keyboard shortcuts, settings dialog.
|
||||||
|
- Offline guarantee: zero network code paths.
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
# Code of Conduct
|
||||||
|
|
||||||
|
## Our Standard
|
||||||
|
|
||||||
|
Everyone participating in this project — contributors, reviewers, and users
|
||||||
|
filing issues — is expected to:
|
||||||
|
|
||||||
|
- be respectful and constructive; critique code, not people;
|
||||||
|
- assume good faith and ask before escalating;
|
||||||
|
- keep discussions on-topic and free of harassment, discrimination, or
|
||||||
|
personal attacks;
|
||||||
|
- respect the clean-room rules in CONTRIBUTING.md when discussing other
|
||||||
|
products.
|
||||||
|
|
||||||
|
## Enforcement
|
||||||
|
|
||||||
|
Maintainers may edit, hide, or remove comments, commits, issues, and PRs that
|
||||||
|
violate this standard, and may temporarily or permanently ban contributors
|
||||||
|
for repeated or egregious behavior.
|
||||||
|
|
||||||
|
## Reporting
|
||||||
|
|
||||||
|
Report unacceptable behavior privately to the maintainers via the contact
|
||||||
|
listed on the project page. Reports are handled confidentially.
|
||||||
+52
-15
@@ -1,24 +1,55 @@
|
|||||||
# Contributing
|
# Contributing
|
||||||
|
|
||||||
Thanks for improving this template.
|
Thanks for improving StepForge.
|
||||||
|
|
||||||
## Before You Start
|
## Before You Start
|
||||||
|
|
||||||
- Open or link the issue that describes the work.
|
- Open or link the issue that describes the work.
|
||||||
- Keep the change small and focused.
|
- Keep the change small and focused.
|
||||||
- If the work does not have an issue yet, create one first so the PR can reference it.
|
- If the work does not have an issue yet, create one first so the PR can
|
||||||
|
reference it.
|
||||||
|
|
||||||
|
## Clean-Room Rules
|
||||||
|
|
||||||
|
StepForge is an independent reimplementation of publicly documented
|
||||||
|
guide-capture workflow patterns. To keep it legally clean:
|
||||||
|
|
||||||
|
- Do **not** use the names, logos, icons, screenshots, or UI strings of
|
||||||
|
commercial documentation products anywhere in code, assets, or docs.
|
||||||
|
- Do **not** copy wording from other products' documentation into the UI.
|
||||||
|
- Do **not** decompile, disassemble, or otherwise inspect proprietary
|
||||||
|
binaries to derive behavior.
|
||||||
|
- Implement behavior from public descriptions and your own design only.
|
||||||
|
- Keep file formats (`.sfgz`, `.sfglt`, guide/step JSON) documented and
|
||||||
|
versioned in `docs/` and `ARCHITECTURE.md`.
|
||||||
|
|
||||||
|
Contributions are accepted under MPL-2.0 with a Developer Certificate of
|
||||||
|
Origin sign-off (`git commit -s`).
|
||||||
|
|
||||||
|
## Offline Rules
|
||||||
|
|
||||||
|
- No network code paths in the application. No telemetry, update checks,
|
||||||
|
license checks, remote fonts, or remote APIs — ever.
|
||||||
|
- No new runtime dependencies without prior maintainer agreement; prefer
|
||||||
|
internal implementations using Node built-ins.
|
||||||
|
|
||||||
## Branching
|
## Branching
|
||||||
|
|
||||||
- Use a branch name that includes the issue number, such as `issue-123-update-readme`.
|
- Use a branch name that includes the issue number, such as
|
||||||
- Keep unrelated cleanup in a separate branch, only have the fix in the branch.
|
`issue-123-update-readme`.
|
||||||
|
- Keep unrelated cleanup in a separate branch, only have the fix in the
|
||||||
|
branch.
|
||||||
|
|
||||||
## Pull Requests
|
## Pull Requests
|
||||||
|
|
||||||
- Every pull request must reference an issue number in the body with `Closes #123`, `Fixes #123`, or `Relates to #123`.
|
- Every pull request must reference an issue number in the body with
|
||||||
- Summarize the change clearly and call out anything a reviewer should verify manually.
|
`Closes #123`, `Fixes #123`, or `Relates to #123`.
|
||||||
- Update docs and templates when the workflow changes.
|
- Summarize the change clearly and call out anything a reviewer should
|
||||||
- If the PR changes the template itself, describe how future contributors should use the new pattern.
|
verify manually.
|
||||||
|
- Update docs when behavior changes, and add a CHANGELOG entry for every
|
||||||
|
user-visible change.
|
||||||
|
- Every exporter or storage change **requires tests**; output changes
|
||||||
|
require updated snapshot fixtures under `tests/fixtures/`.
|
||||||
|
|
||||||
## Tests
|
## Tests
|
||||||
|
|
||||||
@@ -28,11 +59,20 @@ Run the local checks before opening or updating a PR:
|
|||||||
bash tests/run_test.sh
|
bash tests/run_test.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
Put new shell checks in `tests/checks/` so the shared runner picks them up automatically.
|
Put new shell checks in `tests/checks/` so the shared runner picks them up
|
||||||
|
automatically. The shell checks invoke the `node --test` workflow suites in
|
||||||
|
`tests/unit/`.
|
||||||
|
|
||||||
The Gitea workflow in `.gitea/workflows/tests.yaml` runs the same command automatically on pushes and pull requests.
|
Write tests that exercise **real workflows and verify actual output** —
|
||||||
|
create a guide, export it, parse the bytes that came out — rather than
|
||||||
|
grepping for magic strings.
|
||||||
|
|
||||||
Please add lots of tests to each of your PR's and be descriptive with the tests so that the issue doesn't happen again or the feature doesn't get overwritten.
|
The Gitea workflow in `.gitea/workflows/tests.yaml` runs the same command
|
||||||
|
automatically on pushes and pull requests.
|
||||||
|
|
||||||
|
Please add lots of tests to each of your PR's and be descriptive with the
|
||||||
|
tests so that the issue doesn't happen again or the feature doesn't get
|
||||||
|
overwritten.
|
||||||
|
|
||||||
## Review Checklist
|
## Review Checklist
|
||||||
|
|
||||||
@@ -41,7 +81,4 @@ Please add lots of tests to each of your PR's and be descriptive with the tests
|
|||||||
- Any relevant docs or comments are updated.
|
- Any relevant docs or comments are updated.
|
||||||
- The change stays within the intended scope.
|
- The change stays within the intended scope.
|
||||||
- The PR body explains any manual verification that is still needed.
|
- The PR body explains any manual verification that is still needed.
|
||||||
|
- No network calls, no new dependencies, no trademarked assets.
|
||||||
## Notes for Template Maintainers
|
|
||||||
|
|
||||||
If this repository is reused as a starter for another project, adjust the branch naming convention, issue linking rule, and testing command so they match the new project.
|
|
||||||
|
|||||||
@@ -0,0 +1,373 @@
|
|||||||
|
Mozilla Public License Version 2.0
|
||||||
|
==================================
|
||||||
|
|
||||||
|
1. Definitions
|
||||||
|
--------------
|
||||||
|
|
||||||
|
1.1. "Contributor"
|
||||||
|
means each individual or legal entity that creates, contributes to
|
||||||
|
the creation of, or owns Covered Software.
|
||||||
|
|
||||||
|
1.2. "Contributor Version"
|
||||||
|
means the combination of the Contributions of others (if any) used
|
||||||
|
by a Contributor and that particular Contributor's Contribution.
|
||||||
|
|
||||||
|
1.3. "Contribution"
|
||||||
|
means Covered Software of a particular Contributor.
|
||||||
|
|
||||||
|
1.4. "Covered Software"
|
||||||
|
means Source Code Form to which the initial Contributor has attached
|
||||||
|
the notice in Exhibit A, the Executable Form of such Source Code
|
||||||
|
Form, and Modifications of such Source Code Form, in each case
|
||||||
|
including portions thereof.
|
||||||
|
|
||||||
|
1.5. "Incompatible With Secondary Licenses"
|
||||||
|
means
|
||||||
|
|
||||||
|
(a) that the initial Contributor has attached the notice described
|
||||||
|
in Exhibit B to the Covered Software; or
|
||||||
|
|
||||||
|
(b) that the Covered Software was made available under the terms of
|
||||||
|
version 1.1 or earlier of the License, but not also under the
|
||||||
|
terms of a Secondary License.
|
||||||
|
|
||||||
|
1.6. "Executable Form"
|
||||||
|
means any form of the work other than Source Code Form.
|
||||||
|
|
||||||
|
1.7. "Larger Work"
|
||||||
|
means a work that combines Covered Software with other material, in
|
||||||
|
a separate file or files, that is not Covered Software.
|
||||||
|
|
||||||
|
1.8. "License"
|
||||||
|
means this document.
|
||||||
|
|
||||||
|
1.9. "Licensable"
|
||||||
|
means having the right to grant, to the maximum extent possible,
|
||||||
|
whether at the time of the initial grant or subsequently, any and
|
||||||
|
all of the rights conveyed by this License.
|
||||||
|
|
||||||
|
1.10. "Modifications"
|
||||||
|
means any of the following:
|
||||||
|
|
||||||
|
(a) any file in Source Code Form that results from an addition to,
|
||||||
|
deletion from, or modification of the contents of Covered
|
||||||
|
Software; or
|
||||||
|
|
||||||
|
(b) any new file in Source Code Form that contains any Covered
|
||||||
|
Software.
|
||||||
|
|
||||||
|
1.11. "Patent Claims" of a Contributor
|
||||||
|
means any patent claim(s), including without limitation, method,
|
||||||
|
process, and apparatus claims, in any patent Licensable by such
|
||||||
|
Contributor that would be infringed, but for the grant of the
|
||||||
|
License, by the making, using, selling, offering for sale, having
|
||||||
|
made, import, or transfer of either its Contributions or its
|
||||||
|
Contributor Version.
|
||||||
|
|
||||||
|
1.12. "Secondary License"
|
||||||
|
means either the GNU General Public License, Version 2.0, the GNU
|
||||||
|
Lesser General Public License, Version 2.1, the GNU Affero General
|
||||||
|
Public License, Version 3.0, or any later versions of those
|
||||||
|
licenses.
|
||||||
|
|
||||||
|
1.13. "Source Code Form"
|
||||||
|
means the form of the work preferred for making modifications.
|
||||||
|
|
||||||
|
1.14. "You" (or "Your")
|
||||||
|
means an individual or a legal entity exercising rights under this
|
||||||
|
License. For legal entities, "You" includes any entity that
|
||||||
|
controls, is controlled by, or is under common control with You. For
|
||||||
|
purposes of this definition, "control" means (a) the power, direct
|
||||||
|
or indirect, to cause the direction or management of such entity,
|
||||||
|
whether by contract or otherwise, or (b) ownership of more than
|
||||||
|
fifty percent (50%) of the outstanding shares or beneficial
|
||||||
|
ownership of such entity.
|
||||||
|
|
||||||
|
2. License Grants and Conditions
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
2.1. Grants
|
||||||
|
|
||||||
|
Each Contributor hereby grants You a world-wide, royalty-free,
|
||||||
|
non-exclusive license:
|
||||||
|
|
||||||
|
(a) under intellectual property rights (other than patent or trademark)
|
||||||
|
Licensable by such Contributor to use, reproduce, make available,
|
||||||
|
modify, display, perform, distribute, and otherwise exploit its
|
||||||
|
Contributions, either on an unmodified basis, with Modifications, or
|
||||||
|
as part of a Larger Work; and
|
||||||
|
|
||||||
|
(b) under Patent Claims of such Contributor to make, use, sell, offer
|
||||||
|
for sale, have made, import, and otherwise transfer either its
|
||||||
|
Contributions or its Contributor Version.
|
||||||
|
|
||||||
|
2.2. Effective Date
|
||||||
|
|
||||||
|
The licenses granted in Section 2.1 with respect to any Contribution
|
||||||
|
become effective for each Contribution on the date the Contributor first
|
||||||
|
distributes such Contribution.
|
||||||
|
|
||||||
|
2.3. Limitations on Grant Scope
|
||||||
|
|
||||||
|
The licenses granted in this Section 2 are the only rights granted under
|
||||||
|
this License. No additional rights or licenses will be implied from the
|
||||||
|
distribution or licensing of Covered Software under this License.
|
||||||
|
Notwithstanding Section 2.1(b) above, no patent license is granted by a
|
||||||
|
Contributor:
|
||||||
|
|
||||||
|
(a) for any code that a Contributor has removed from Covered Software;
|
||||||
|
or
|
||||||
|
|
||||||
|
(b) for infringements caused by: (i) Your and any other third party's
|
||||||
|
modifications of Covered Software, or (ii) the combination of its
|
||||||
|
Contributions with other software (except as part of its Contributor
|
||||||
|
Version); or
|
||||||
|
|
||||||
|
(c) under Patent Claims infringed by Covered Software in the absence of
|
||||||
|
its Contributions.
|
||||||
|
|
||||||
|
This License does not grant any rights in the trademarks, service marks,
|
||||||
|
or logos of any Contributor (except as may be necessary to comply with
|
||||||
|
the notice requirements in Section 3.4).
|
||||||
|
|
||||||
|
2.4. Subsequent Licenses
|
||||||
|
|
||||||
|
No Contributor makes additional grants as a result of Your choice to
|
||||||
|
distribute the Covered Software under a subsequent version of this
|
||||||
|
License (see Section 10.2) or under the terms of a Secondary License (if
|
||||||
|
permitted under the terms of Section 3.3).
|
||||||
|
|
||||||
|
2.5. Representation
|
||||||
|
|
||||||
|
Each Contributor represents that the Contributor believes its
|
||||||
|
Contributions are its original creation(s) or it has sufficient rights
|
||||||
|
to grant the rights to its Contributions conveyed by this License.
|
||||||
|
|
||||||
|
2.6. Fair Use
|
||||||
|
|
||||||
|
This License is not intended to limit any rights You have under
|
||||||
|
applicable copyright doctrines of fair use, fair dealing, or other
|
||||||
|
equivalents.
|
||||||
|
|
||||||
|
2.7. Conditions
|
||||||
|
|
||||||
|
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
|
||||||
|
in Section 2.1.
|
||||||
|
|
||||||
|
3. Responsibilities
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
3.1. Distribution of Source Form
|
||||||
|
|
||||||
|
All distribution of Covered Software in Source Code Form, including any
|
||||||
|
Modifications that You create or to which You contribute, must be under
|
||||||
|
the terms of this License. You must inform recipients that the Source
|
||||||
|
Code Form of the Covered Software is governed by the terms of this
|
||||||
|
License, and how they can obtain a copy of this License. You may not
|
||||||
|
attempt to alter or restrict the recipients' rights in the Source Code
|
||||||
|
Form.
|
||||||
|
|
||||||
|
3.2. Distribution of Executable Form
|
||||||
|
|
||||||
|
If You distribute Covered Software in Executable Form then:
|
||||||
|
|
||||||
|
(a) such Covered Software must also be made available in Source Code
|
||||||
|
Form, as described in Section 3.1, and You must inform recipients of
|
||||||
|
the Executable Form how they can obtain a copy of such Source Code
|
||||||
|
Form by reasonable means in a timely manner, at a charge no more
|
||||||
|
than the cost of distribution to the recipient; and
|
||||||
|
|
||||||
|
(b) You may distribute such Executable Form under the terms of this
|
||||||
|
License, or sublicense it under different terms, provided that the
|
||||||
|
license for the Executable Form does not attempt to limit or alter
|
||||||
|
the recipients' rights in the Source Code Form under this License.
|
||||||
|
|
||||||
|
3.3. Distribution of a Larger Work
|
||||||
|
|
||||||
|
You may create and distribute a Larger Work under terms of Your choice,
|
||||||
|
provided that You also comply with the requirements of this License for
|
||||||
|
the Covered Software. If the Larger Work is a combination of Covered
|
||||||
|
Software with a work governed by one or more Secondary Licenses, and the
|
||||||
|
Covered Software is not Incompatible With Secondary Licenses, this
|
||||||
|
License permits You to additionally distribute such Covered Software
|
||||||
|
under the terms of such Secondary License(s), so that the recipient of
|
||||||
|
the Larger Work may, at their option, further distribute the Covered
|
||||||
|
Software under the terms of either this License or such Secondary
|
||||||
|
License(s).
|
||||||
|
|
||||||
|
3.4. Notices
|
||||||
|
|
||||||
|
You may not remove or alter the substance of any license notices
|
||||||
|
(including copyright notices, patent notices, disclaimers of warranty,
|
||||||
|
or limitations of liability) contained within the Source Code Form of
|
||||||
|
the Covered Software, except that You may alter any license notices to
|
||||||
|
the extent required to remedy known factual inaccuracies.
|
||||||
|
|
||||||
|
3.5. Application of Additional Terms
|
||||||
|
|
||||||
|
You may choose to offer, and to charge a fee for, warranty, support,
|
||||||
|
indemnity or liability obligations to one or more recipients of Covered
|
||||||
|
Software. However, You may do so only on Your own behalf, and not on
|
||||||
|
behalf of any Contributor. You must make it absolutely clear that any
|
||||||
|
such warranty, support, indemnity, or liability obligation is offered by
|
||||||
|
You alone, and You hereby agree to indemnify every Contributor for any
|
||||||
|
liability incurred by such Contributor as a result of warranty, support,
|
||||||
|
indemnity or liability terms You offer. You may include additional
|
||||||
|
disclaimers of warranty and limitations of liability specific to any
|
||||||
|
jurisdiction.
|
||||||
|
|
||||||
|
4. Inability to Comply Due to Statute or Regulation
|
||||||
|
---------------------------------------------------
|
||||||
|
|
||||||
|
If it is impossible for You to comply with any of the terms of this
|
||||||
|
License with respect to some or all of the Covered Software due to
|
||||||
|
statute, judicial order, or regulation then You must: (a) comply with
|
||||||
|
the terms of this License to the maximum extent possible; and (b)
|
||||||
|
describe the limitations and the code they affect. Such description must
|
||||||
|
be placed in a text file included with all distributions of the Covered
|
||||||
|
Software under this License. Except to the extent prohibited by statute
|
||||||
|
or regulation, such description must be sufficiently detailed for a
|
||||||
|
recipient of ordinary skill to be able to understand it.
|
||||||
|
|
||||||
|
5. Termination
|
||||||
|
--------------
|
||||||
|
|
||||||
|
5.1. The rights granted under this License will terminate automatically
|
||||||
|
if You fail to comply with any of its terms. However, if You become
|
||||||
|
compliant, then the rights granted under this License from a particular
|
||||||
|
Contributor are reinstated (a) provisionally, unless and until such
|
||||||
|
Contributor explicitly and finally terminates Your grants, and (b) on an
|
||||||
|
ongoing basis, if such Contributor fails to notify You of the
|
||||||
|
non-compliance by some reasonable means prior to 60 days after You have
|
||||||
|
come back into compliance. Moreover, Your grants from a particular
|
||||||
|
Contributor are reinstated on an ongoing basis if such Contributor
|
||||||
|
notifies You of the non-compliance by some reasonable means, this is the
|
||||||
|
first time You have received notice of non-compliance with this License
|
||||||
|
from such Contributor, and You become compliant prior to 30 days after
|
||||||
|
Your receipt of the notice.
|
||||||
|
|
||||||
|
5.2. If You initiate litigation against any entity by asserting a patent
|
||||||
|
infringement claim (excluding declaratory judgment actions,
|
||||||
|
counter-claims, and cross-claims) alleging that a Contributor Version
|
||||||
|
directly or indirectly infringes any patent, then the rights granted to
|
||||||
|
You by any and all Contributors for the Covered Software under Section
|
||||||
|
2.1 of this License shall terminate.
|
||||||
|
|
||||||
|
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
|
||||||
|
end user license agreements (excluding distributors and resellers) which
|
||||||
|
have been validly granted by You or Your distributors under this License
|
||||||
|
prior to termination shall survive termination.
|
||||||
|
|
||||||
|
************************************************************************
|
||||||
|
* *
|
||||||
|
* 6. Disclaimer of Warranty *
|
||||||
|
* ------------------------- *
|
||||||
|
* *
|
||||||
|
* Covered Software is provided under this License on an "as is" *
|
||||||
|
* basis, without warranty of any kind, either expressed, implied, or *
|
||||||
|
* statutory, including, without limitation, warranties that the *
|
||||||
|
* Covered Software is free of defects, merchantable, fit for a *
|
||||||
|
* particular purpose or non-infringing. The entire risk as to the *
|
||||||
|
* quality and performance of the Covered Software is with You. *
|
||||||
|
* Should any Covered Software prove defective in any respect, You *
|
||||||
|
* (not any Contributor) assume the cost of any necessary servicing, *
|
||||||
|
* repair, or correction. This disclaimer of warranty constitutes an *
|
||||||
|
* essential part of this License. No use of any Covered Software is *
|
||||||
|
* authorized under this License except under this disclaimer. *
|
||||||
|
* *
|
||||||
|
************************************************************************
|
||||||
|
|
||||||
|
************************************************************************
|
||||||
|
* *
|
||||||
|
* 7. Limitation of Liability *
|
||||||
|
* -------------------------- *
|
||||||
|
* *
|
||||||
|
* Under no circumstances and under no legal theory, whether tort *
|
||||||
|
* (including negligence), contract, or otherwise, shall any *
|
||||||
|
* Contributor, or anyone who distributes Covered Software as *
|
||||||
|
* permitted above, be liable to You for any direct, indirect, *
|
||||||
|
* special, incidental, or consequential damages of any character *
|
||||||
|
* including, without limitation, damages for lost profits, loss of *
|
||||||
|
* goodwill, work stoppage, computer failure or malfunction, or any *
|
||||||
|
* and all other commercial damages or losses, even if such party *
|
||||||
|
* shall have been informed of the possibility of such damages. This *
|
||||||
|
* limitation of liability shall not apply to liability for death or *
|
||||||
|
* personal injury resulting from such party's negligence to the *
|
||||||
|
* extent applicable law prohibits such limitation. Some *
|
||||||
|
* jurisdictions do not allow the exclusion or limitation of *
|
||||||
|
* incidental or consequential damages, so this exclusion and *
|
||||||
|
* limitation may not apply to You. *
|
||||||
|
* *
|
||||||
|
************************************************************************
|
||||||
|
|
||||||
|
8. Litigation
|
||||||
|
-------------
|
||||||
|
|
||||||
|
Any litigation relating to this License may be brought only in the
|
||||||
|
courts of a jurisdiction where the defendant maintains its principal
|
||||||
|
place of business and such litigation shall be governed by laws of that
|
||||||
|
jurisdiction, without reference to its conflict-of-law provisions.
|
||||||
|
Nothing in this Section shall prevent a party's ability to bring
|
||||||
|
cross-claims or counter-claims.
|
||||||
|
|
||||||
|
9. Miscellaneous
|
||||||
|
----------------
|
||||||
|
|
||||||
|
This License represents the complete agreement concerning the subject
|
||||||
|
matter hereof. If any provision of this License is held to be
|
||||||
|
unenforceable, such provision shall be reformed only to the extent
|
||||||
|
necessary to make it enforceable. Any law or regulation which provides
|
||||||
|
that the language of a contract shall be construed against the drafter
|
||||||
|
shall not be used to construe this License against a Contributor.
|
||||||
|
|
||||||
|
10. Versions of the License
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
10.1. New Versions
|
||||||
|
|
||||||
|
Mozilla Foundation is the license steward. Except as provided in Section
|
||||||
|
10.3, no one other than the license steward has the right to modify or
|
||||||
|
publish new versions of this License. Each version will be given a
|
||||||
|
distinguishing version number.
|
||||||
|
|
||||||
|
10.2. Effect of New Versions
|
||||||
|
|
||||||
|
You may distribute the Covered Software under the terms of the version
|
||||||
|
of the License under which You originally received the Covered Software,
|
||||||
|
or under the terms of any subsequent version published by the license
|
||||||
|
steward.
|
||||||
|
|
||||||
|
10.3. Modified Versions
|
||||||
|
|
||||||
|
If you create software not governed by this License, and you want to
|
||||||
|
create a new license for such software, you may create and use a
|
||||||
|
modified version of this License if you rename the license and remove
|
||||||
|
any references to the name of the license steward (except to note that
|
||||||
|
such modified license differs from this License).
|
||||||
|
|
||||||
|
10.4. Distributing Source Code Form that is Incompatible With Secondary
|
||||||
|
Licenses
|
||||||
|
|
||||||
|
If You choose to distribute Source Code Form that is Incompatible With
|
||||||
|
Secondary Licenses under the terms of this version of the License, the
|
||||||
|
notice described in Exhibit B of this License must be attached.
|
||||||
|
|
||||||
|
Exhibit A - Source Code Form License Notice
|
||||||
|
-------------------------------------------
|
||||||
|
|
||||||
|
This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
If it is not possible or desirable to put the notice in a particular
|
||||||
|
file, then You may include the notice in a location (such as a LICENSE
|
||||||
|
file in a relevant directory) where a recipient would be likely to look
|
||||||
|
for such a notice.
|
||||||
|
|
||||||
|
You may add additional accurate notices of copyright ownership.
|
||||||
|
|
||||||
|
Exhibit B - "Incompatible With Secondary Licenses" Notice
|
||||||
|
---------------------------------------------------------
|
||||||
|
|
||||||
|
This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||||
|
defined by the Mozilla Public License, v. 2.0.
|
||||||
@@ -1,32 +1,131 @@
|
|||||||
# Title
|
# StepForge
|
||||||
|
|
||||||
|
StepForge is a **fully offline**, open-source desktop app for Windows and
|
||||||
|
Linux that captures step-by-step workflows as screenshots, lets you annotate
|
||||||
|
and describe each step in a focused three-pane editor, and exports the result
|
||||||
|
to JSON, Markdown, HTML (simple and rich), PDF, animated GIF, image bundles,
|
||||||
|
DOCX, and PPTX.
|
||||||
|
|
||||||
|
It is an independent offline desktop guide-capture tool inspired by publicly
|
||||||
|
documented workflow patterns of commercial documentation tools. It contains no
|
||||||
|
third-party branding, assets, or code from those tools, and it never talks to
|
||||||
|
the network: no telemetry, no update checks, no license checks, no cloud, no
|
||||||
|
remote AI.
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
|
The core workflow:
|
||||||
|
|
||||||
|
1. **Capture** — take full-screen, active-window, or region screenshots with
|
||||||
|
configurable delay, pause/resume, and global hotkeys; or import images and
|
||||||
|
paste from the clipboard.
|
||||||
|
2. **Annotate** — rectangles, ovals, lines, arrows, text, tooltips, numbered
|
||||||
|
markers, blur, highlight, magnify, and crop on a resolution-independent
|
||||||
|
annotation scene graph.
|
||||||
|
3. **Describe** — rich-text titles and descriptions, informational text
|
||||||
|
blocks, code blocks, tables, step links, and placeholders.
|
||||||
|
4. **Export** — every exporter renders from the same normalized Render AST,
|
||||||
|
so output is deterministic across formats.
|
||||||
|
|
||||||
|
```text
|
||||||
|
┌────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
│ StepForge > Reset Password SOP [Capture] [Export] [Save] │
|
||||||
|
├──────────────────┬──────────────────────────────────┬──────────────────────┤
|
||||||
|
│ Steps │ Canvas │ Properties │
|
||||||
|
│ 1 Open Users │ ┌────────────────────────────┐ │ Title │
|
||||||
|
│ 2 Search account │ │ [tooltip] │ │ [Reset password] │
|
||||||
|
│ 3 Click Reset │ │ ↘ ┌────────────┐ │ │ Description │
|
||||||
|
│ 3.1 Warning │ │ │ Reset btn │ │ │ [rich text editor] │
|
||||||
|
│ 4 Done │ │ └────────────┘ │ │ Text blocks │
|
||||||
|
│ [Add Step] │ └────────────────────────────┘ │ Step settings │
|
||||||
|
├──────────────────┴──────────────────────────────────┴──────────────────────┤
|
||||||
|
│ Tools: [Select][Rect][Oval][Line][Arrow][Text][Tooltip][#][Blur][Hi][Crop] │
|
||||||
|
└────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
## What's Included
|
||||||
|
|
||||||
|
- **Guide library** with folders, favorites, title search, full-text search,
|
||||||
|
duplicate/move/delete, and a quick-actions palette (`Ctrl+/`).
|
||||||
|
- **Capture engine** — full screen, active window, and region capture with
|
||||||
|
delay, pause/resume, hotkeys, click markers, clipboard paste, and PNG/JPEG/
|
||||||
|
GIF import.
|
||||||
|
- **Three-pane editor** — step tree with substeps, statuses
|
||||||
|
(todo/in-progress/done), hidden/skipped steps, focused view (zoom/pan that
|
||||||
|
never mutates the original image), autosave, and command-stack undo/redo.
|
||||||
|
- **Annotation canvas** — normalized JSON scene graph with
|
||||||
|
resolution-independent coordinates; annotations render identically in the
|
||||||
|
editor and in every exporter.
|
||||||
|
- **Sharing & backups** — single-file `.sfgz` archives (zip-based, path-
|
||||||
|
traversal validated), linked guides with `.lock-sfgz` lock files and
|
||||||
|
explicit save, plus automated snapshot backups and restore.
|
||||||
|
- **Exports** — JSON, Markdown, Simple HTML, Rich HTML (checkboxes + floating
|
||||||
|
TOC), PDF, animated GIF, image bundle, DOCX, and PPTX, with per-format
|
||||||
|
export templates shareable as `.sfglt` files.
|
||||||
|
- **Settings & theming** — system/light/dark themes, capture options,
|
||||||
|
keyboard shortcuts, preview step count.
|
||||||
|
|
||||||
|
Everything except the Electron shell is dependency-free Node.js: the ZIP,
|
||||||
|
PNG, GIF, PDF, DOCX, and PPTX writers are all implemented in this repository
|
||||||
|
using only Node built-ins.
|
||||||
|
|
||||||
## Getting Started
|
## Getting Started
|
||||||
|
|
||||||
|
Requirements: Node.js 20+ and npm (Electron is the only dependency).
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install # one-time, fetches the Electron shell
|
||||||
|
npm start # launch StepForge
|
||||||
|
```
|
||||||
|
|
||||||
|
First run creates the local data directory (`~/.local/share/stepforge` on
|
||||||
|
Linux, `%APPDATA%/stepforge` on Windows; override with `STEPFORGE_DATA_DIR`).
|
||||||
|
|
||||||
## Testing
|
## Testing
|
||||||
|
|
||||||
Please create your tests so that when the following is ran it automatically tests your test.
|
Please create your tests so that when the following is ran it automatically
|
||||||
|
tests your test.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
bash tests/run_test.sh
|
bash tests/run_test.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The runner executes every `tests/checks/test_*.sh` script; those scripts run
|
||||||
|
the workflow test suites under `tests/unit/` with `node --test`. The tests
|
||||||
|
exercise real workflows — creating guides, round-tripping archives, exporting
|
||||||
|
documents, and validating the bytes of the output — not string matching.
|
||||||
|
|
||||||
|
## Building & Packaging
|
||||||
|
|
||||||
|
```bash
|
||||||
|
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
|
||||||
|
```
|
||||||
|
|
||||||
|
See [build/build_report.md](build/build_report.md) for what was produced on
|
||||||
|
this machine and which packaging tools were unavailable.
|
||||||
|
|
||||||
|
## Offline Guarantee
|
||||||
|
|
||||||
|
The shipping app makes **zero network calls**. There is no telemetry, no
|
||||||
|
update check, no license validation, no cloud sync, no account system, and no
|
||||||
|
remote AI. Exports embed no remote fonts or CDN references. See
|
||||||
|
[SECURITY.md](SECURITY.md) for the threat model.
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
See [CONTRIBUTING.md](CONTRIBUTING.md) for the full contribution flow, including the issue-number requirement for every pull request.
|
See [CONTRIBUTING.md](CONTRIBUTING.md) for the full contribution flow,
|
||||||
|
including the issue-number requirement for every pull request and the
|
||||||
|
clean-room rules.
|
||||||
|
|
||||||
## Repository Layout
|
## Repository Layout
|
||||||
|
|
||||||
See [ARCHITECTURE.md](ARCHITECTURE.md) to see the repo layout.
|
See [ARCHITECTURE.md](ARCHITECTURE.md) to see the repo layout.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Application code is licensed under [MPL-2.0](LICENSE). Bundled example
|
||||||
|
guides, templates, and screenshots are CC-BY-4.0 unless noted otherwise.
|
||||||
|
|||||||
+69
@@ -0,0 +1,69 @@
|
|||||||
|
# Security
|
||||||
|
|
||||||
|
## Offline Guarantee
|
||||||
|
|
||||||
|
StepForge ships with **zero network code paths**. The application:
|
||||||
|
|
||||||
|
- opens no sockets and performs no HTTP requests,
|
||||||
|
- has no telemetry, crash reporting, or analytics,
|
||||||
|
- performs no update checks and no license validation,
|
||||||
|
- has no account system, cloud sync, or remote AI integration,
|
||||||
|
- embeds no remote fonts, CDNs, or external references in exports.
|
||||||
|
|
||||||
|
The only network activity in the project's lifetime is the one-time
|
||||||
|
development fetch of the Electron shell via npm (see
|
||||||
|
`build/agent_audit.md`). The packaged app never goes online.
|
||||||
|
|
||||||
|
## Threat Model
|
||||||
|
|
||||||
|
Because the app is local-only, the realistic attack surface is **malicious
|
||||||
|
files opened by the user**:
|
||||||
|
|
||||||
|
### Archive imports (`.sfgz`, `.sfglt`)
|
||||||
|
|
||||||
|
Both formats are zip files. The reader in `core/zip.js` validates every entry
|
||||||
|
before extraction:
|
||||||
|
|
||||||
|
- entry names must be relative, must not contain `..` segments, drive
|
||||||
|
letters, or absolute paths;
|
||||||
|
- entries are extracted only beneath the destination directory (resolved
|
||||||
|
path is verified to stay inside it);
|
||||||
|
- file sizes are taken from actual inflated data, not trusted headers;
|
||||||
|
- unknown entries outside the documented layout are ignored.
|
||||||
|
|
||||||
|
### Image imports (PNG/JPEG/GIF)
|
||||||
|
|
||||||
|
Imported images are decoded by the platform image codecs in the Electron
|
||||||
|
shell and re-encoded to PNG before storage. The pure-JS PNG decoder in
|
||||||
|
`core/png.js` (used by exporters) rejects malformed dimensions, oversized
|
||||||
|
allocations, and bad CRCs.
|
||||||
|
|
||||||
|
### Linked guides and lock files
|
||||||
|
|
||||||
|
Shared `.sfgz` files opened in *linked mode* use a sidecar lock file
|
||||||
|
(`<name>.lock-sfgz`) containing the holder's machine name and timestamp.
|
||||||
|
This is an advisory lock for coordination on shared folders, **not** a
|
||||||
|
security boundary: a hostile or crashed peer can delete it. Conflicts are
|
||||||
|
surfaced to the user with keep-editing / discard options; the format is
|
||||||
|
last-write-wins and that risk is documented in the UI.
|
||||||
|
|
||||||
|
### Local data at rest
|
||||||
|
|
||||||
|
The guide store is **not encrypted at rest** — it inherits the user account's
|
||||||
|
filesystem protections, like any document folder. If you need encrypted
|
||||||
|
sharing, encrypt the `.sfgz` with external tooling; native encrypted archives
|
||||||
|
are a tracked enhancement, not a current feature.
|
||||||
|
|
||||||
|
## Renderer Hardening
|
||||||
|
|
||||||
|
The Electron renderer runs with `contextIsolation: true` and
|
||||||
|
`nodeIntegration: false`; the only privileged surface is the explicit
|
||||||
|
allowlisted IPC API in `app/preload.js`. Guide description HTML is sanitized
|
||||||
|
(allowlisted tags/attributes, no scripts, no event handlers, no external
|
||||||
|
URLs) before storage and again before rendering or export.
|
||||||
|
|
||||||
|
## Reporting
|
||||||
|
|
||||||
|
Report vulnerabilities by opening an issue marked `security` (this is a
|
||||||
|
local-only tool, so coordinated disclosure pressure is low; do not include
|
||||||
|
exploit archives directly — describe the structure instead).
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
# Environment Audit
|
||||||
|
|
||||||
|
Audit performed 2026-06-10 before stack selection, as required by the build
|
||||||
|
specification in `prompt.md`.
|
||||||
|
|
||||||
|
## Host
|
||||||
|
|
||||||
|
| Item | Value |
|
||||||
|
|---|---|
|
||||||
|
| OS | Linux 6.6.87.2-microsoft-standard-WSL2 (Ubuntu userland, x86_64) |
|
||||||
|
| Display | WSLg available (`DISPLAY=:0`, `WAYLAND_DISPLAY=wayland-0`) — GUI apps can run |
|
||||||
|
| Shell | bash |
|
||||||
|
|
||||||
|
## Toolchains
|
||||||
|
|
||||||
|
| Toolchain | Present | Detail |
|
||||||
|
|---|---|---|
|
||||||
|
| Node.js | yes | v20.20.2 (`/usr/bin/node`) |
|
||||||
|
| npm | yes | 10.8.2, cache at `~/.npm/_cacache` |
|
||||||
|
| Rust / Cargo | **no** | not installed, no `~/.cargo/registry` cache |
|
||||||
|
| .NET SDK | **no** | not installed |
|
||||||
|
| Python | yes | 3.12.3 (venv), no GUI toolkit verified |
|
||||||
|
|
||||||
|
## Packaging tools
|
||||||
|
|
||||||
|
| Tool | Present |
|
||||||
|
|---|---|
|
||||||
|
| dpkg-deb | yes (`/usr/bin/dpkg-deb`) |
|
||||||
|
| rpmbuild | no |
|
||||||
|
| appimagetool | no |
|
||||||
|
| WiX (MSI) | no |
|
||||||
|
| NSIS / Inno Setup | no |
|
||||||
|
|
||||||
|
## Vendored dependencies
|
||||||
|
|
||||||
|
`./vendor/` does not exist. No vendored dependencies are present on disk.
|
||||||
|
|
||||||
|
## Network
|
||||||
|
|
||||||
|
`registry.npmjs.org` is reachable (HTTP 200).
|
||||||
|
|
||||||
|
## Stack selection and recorded deviation
|
||||||
|
|
||||||
|
The specification's stack-selection rule prefers Rust + Tauri, then Rust +
|
||||||
|
immediate-mode UI, then .NET/Avalonia, and says never to choose a path that
|
||||||
|
requires network dependency resolution.
|
||||||
|
|
||||||
|
**None of the offline-capable GUI paths exist on this machine**: there is no
|
||||||
|
Rust toolchain, no cargo registry cache, no .NET SDK, and no `./vendor`
|
||||||
|
directory. The only installed application runtime is Node.js. A desktop GUI
|
||||||
|
cannot be produced from Node.js built-ins alone.
|
||||||
|
|
||||||
|
**Decision:** Node.js core + Electron desktop shell.
|
||||||
|
|
||||||
|
- All product logic (schema, storage, archives, locks, search, placeholder
|
||||||
|
expansion, render AST, and every exporter — ZIP, PNG, GIF, PDF, DOCX, PPTX,
|
||||||
|
HTML, Markdown, JSON) is implemented **dependency-free** in `core/` and
|
||||||
|
`exporters/` using only Node built-ins (`node:fs`, `node:zlib`,
|
||||||
|
`node:crypto`, ...). This code runs and is tested fully offline with
|
||||||
|
`node --test`.
|
||||||
|
- Electron is the **single third-party dependency**, used only as the desktop
|
||||||
|
shell (window, canvas UI, screen capture, global hotkeys, clipboard). It was
|
||||||
|
fetched from the npm registry once at development time because no offline
|
||||||
|
GUI toolchain exists on this machine. This is a recorded deviation from the
|
||||||
|
"never fetch from the network" build rule, chosen over the alternative of
|
||||||
|
shipping no GUI at all.
|
||||||
|
- The **shipped application contains zero network code paths**: no telemetry,
|
||||||
|
no update checks, no license checks, no remote AI, no sockets.
|
||||||
|
|
||||||
|
### Fallbacks chosen for missing components
|
||||||
|
|
||||||
|
| Spec preference | Fallback used | Reason |
|
||||||
|
|---|---|---|
|
||||||
|
| SQLite + FTS5 search index | Pure-JS inverted index persisted as JSON under `library/index/` | Node 20 has no built-in SQLite; native modules would add dependencies |
|
||||||
|
| HTML/CSS → PDF backend | Native PDF generation from the render AST (hand-rolled PDF writer) | Deterministic, testable headlessly, no browser dependency in the export path |
|
||||||
|
| OCR title prefill | Template-based title generation (capture mode + timestamp + window title when available) | No offline OCR engine present |
|
||||||
|
| MSI / NSIS / AppImage / RPM | Portable archives + `.deb` via dpkg-deb; spec files emitted for the missing tools | Tools absent (see table above), recorded in `build/build_report.md` |
|
||||||
Generated
+872
@@ -0,0 +1,872 @@
|
|||||||
|
{
|
||||||
|
"name": "autodoc",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"lockfileVersion": 3,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"name": "autodoc",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"license": "ISC",
|
||||||
|
"devDependencies": {
|
||||||
|
"electron": "^41.7.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@electron/get": {
|
||||||
|
"version": "2.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@electron/get/-/get-2.0.3.tgz",
|
||||||
|
"integrity": "sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"debug": "^4.1.1",
|
||||||
|
"env-paths": "^2.2.0",
|
||||||
|
"fs-extra": "^8.1.0",
|
||||||
|
"got": "^11.8.5",
|
||||||
|
"progress": "^2.0.3",
|
||||||
|
"semver": "^6.2.0",
|
||||||
|
"sumchecker": "^3.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"global-agent": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@sindresorhus/is": {
|
||||||
|
"version": "4.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz",
|
||||||
|
"integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sindresorhus/is?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@szmarczak/http-timer": {
|
||||||
|
"version": "4.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz",
|
||||||
|
"integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"defer-to-connect": "^2.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/cacheable-request": {
|
||||||
|
"version": "6.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz",
|
||||||
|
"integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/http-cache-semantics": "*",
|
||||||
|
"@types/keyv": "^3.1.4",
|
||||||
|
"@types/node": "*",
|
||||||
|
"@types/responselike": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/http-cache-semantics": {
|
||||||
|
"version": "4.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz",
|
||||||
|
"integrity": "sha512-L3LgimLHXtGkWikKnsPg0/VFx9OGZaC+eN1u4r+OB1XRqH3meBIAVC2zr1WdMH+RHmnRkqliQAOHNJ/E0j/e0Q==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/@types/keyv": {
|
||||||
|
"version": "3.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz",
|
||||||
|
"integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/node": {
|
||||||
|
"version": "24.13.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.13.1.tgz",
|
||||||
|
"integrity": "sha512-RSpUJGmvsJ1ZeBehQZFhIdpsz+bIpES0nIQXko4Ybq+N+kX6XvOq3Jo+iJ82FWLdblFq85AsMikd3m35jgezYg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"undici-types": "~7.18.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/responselike": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/yauzl": {
|
||||||
|
"version": "2.10.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz",
|
||||||
|
"integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/boolean": {
|
||||||
|
"version": "3.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz",
|
||||||
|
"integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==",
|
||||||
|
"deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"node_modules/buffer-crc32": {
|
||||||
|
"version": "0.2.13",
|
||||||
|
"resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
|
||||||
|
"integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/cacheable-lookup": {
|
||||||
|
"version": "5.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz",
|
||||||
|
"integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.6.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/cacheable-request": {
|
||||||
|
"version": "7.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz",
|
||||||
|
"integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"clone-response": "^1.0.2",
|
||||||
|
"get-stream": "^5.1.0",
|
||||||
|
"http-cache-semantics": "^4.0.0",
|
||||||
|
"keyv": "^4.0.0",
|
||||||
|
"lowercase-keys": "^2.0.0",
|
||||||
|
"normalize-url": "^6.0.1",
|
||||||
|
"responselike": "^2.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/clone-response": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"mimic-response": "^1.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/debug": {
|
||||||
|
"version": "4.4.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
|
||||||
|
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"ms": "^2.1.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"supports-color": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/decompress-response": {
|
||||||
|
"version": "6.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
|
||||||
|
"integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"mimic-response": "^3.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/decompress-response/node_modules/mimic-response": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/defer-to-connect": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/define-data-property": {
|
||||||
|
"version": "1.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
|
||||||
|
"integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"es-define-property": "^1.0.0",
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"gopd": "^1.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/define-properties": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
|
||||||
|
"integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"define-data-property": "^1.0.1",
|
||||||
|
"has-property-descriptors": "^1.0.0",
|
||||||
|
"object-keys": "^1.1.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/detect-node": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"node_modules/electron": {
|
||||||
|
"version": "41.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/electron/-/electron-41.7.1.tgz",
|
||||||
|
"integrity": "sha512-pdRvNNP99Qfvs1lyIxo/sfIGAwJP0CrJFNCE3goFKc7/fV+kjK3EPxx5Nt6sLTkzqTyeRYylpwPUfpeGojiyyw==",
|
||||||
|
"dev": true,
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@electron/get": "^2.0.0",
|
||||||
|
"@types/node": "^24.9.0",
|
||||||
|
"extract-zip": "^2.0.1"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"electron": "cli.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 12.20.55"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/end-of-stream": {
|
||||||
|
"version": "1.4.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz",
|
||||||
|
"integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"once": "^1.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/env-paths": {
|
||||||
|
"version": "2.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
|
||||||
|
"integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/es-define-property": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/es-errors": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/es6-error": {
|
||||||
|
"version": "4.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz",
|
||||||
|
"integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"node_modules/escape-string-regexp": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/extract-zip": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "BSD-2-Clause",
|
||||||
|
"dependencies": {
|
||||||
|
"debug": "^4.1.1",
|
||||||
|
"get-stream": "^5.1.0",
|
||||||
|
"yauzl": "^2.10.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"extract-zip": "cli.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10.17.0"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"@types/yauzl": "^2.9.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/fd-slicer": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"pend": "~1.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/fs-extra": {
|
||||||
|
"version": "8.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
|
||||||
|
"integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"graceful-fs": "^4.2.0",
|
||||||
|
"jsonfile": "^4.0.0",
|
||||||
|
"universalify": "^0.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6 <7 || >=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/get-stream": {
|
||||||
|
"version": "5.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
|
||||||
|
"integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"pump": "^3.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/global-agent": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "BSD-3-Clause",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"boolean": "^3.0.1",
|
||||||
|
"es6-error": "^4.1.1",
|
||||||
|
"matcher": "^3.0.0",
|
||||||
|
"roarr": "^2.15.3",
|
||||||
|
"semver": "^7.3.2",
|
||||||
|
"serialize-error": "^7.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/global-agent/node_modules/semver": {
|
||||||
|
"version": "7.8.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.8.4.tgz",
|
||||||
|
"integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"optional": true,
|
||||||
|
"bin": {
|
||||||
|
"semver": "bin/semver.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/globalthis": {
|
||||||
|
"version": "1.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz",
|
||||||
|
"integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"define-properties": "^1.2.1",
|
||||||
|
"gopd": "^1.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/gopd": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/got": {
|
||||||
|
"version": "11.8.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz",
|
||||||
|
"integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@sindresorhus/is": "^4.0.0",
|
||||||
|
"@szmarczak/http-timer": "^4.0.5",
|
||||||
|
"@types/cacheable-request": "^6.0.1",
|
||||||
|
"@types/responselike": "^1.0.0",
|
||||||
|
"cacheable-lookup": "^5.0.3",
|
||||||
|
"cacheable-request": "^7.0.2",
|
||||||
|
"decompress-response": "^6.0.0",
|
||||||
|
"http2-wrapper": "^1.0.0-beta.5.2",
|
||||||
|
"lowercase-keys": "^2.0.0",
|
||||||
|
"p-cancelable": "^2.0.0",
|
||||||
|
"responselike": "^2.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.19.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sindresorhus/got?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/graceful-fs": {
|
||||||
|
"version": "4.2.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
|
||||||
|
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC"
|
||||||
|
},
|
||||||
|
"node_modules/has-property-descriptors": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"es-define-property": "^1.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/http-cache-semantics": {
|
||||||
|
"version": "4.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz",
|
||||||
|
"integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "BSD-2-Clause"
|
||||||
|
},
|
||||||
|
"node_modules/http2-wrapper": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"quick-lru": "^5.1.1",
|
||||||
|
"resolve-alpn": "^1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.19.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/json-buffer": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/json-stringify-safe": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"node_modules/jsonfile": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optionalDependencies": {
|
||||||
|
"graceful-fs": "^4.1.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/keyv": {
|
||||||
|
"version": "4.5.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
|
||||||
|
"integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"json-buffer": "3.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/lowercase-keys": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/matcher": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"escape-string-regexp": "^4.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/mimic-response": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ms": {
|
||||||
|
"version": "2.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||||
|
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/normalize-url": {
|
||||||
|
"version": "6.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz",
|
||||||
|
"integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/object-keys": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/once": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||||
|
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"wrappy": "1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/p-cancelable": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/pend": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/progress": {
|
||||||
|
"version": "2.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
|
||||||
|
"integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/pump": {
|
||||||
|
"version": "3.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz",
|
||||||
|
"integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"end-of-stream": "^1.1.0",
|
||||||
|
"once": "^1.3.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/quick-lru": {
|
||||||
|
"version": "5.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz",
|
||||||
|
"integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/resolve-alpn": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz",
|
||||||
|
"integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/responselike": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"lowercase-keys": "^2.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/roarr": {
|
||||||
|
"version": "2.15.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz",
|
||||||
|
"integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "BSD-3-Clause",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"boolean": "^3.0.1",
|
||||||
|
"detect-node": "^2.0.4",
|
||||||
|
"globalthis": "^1.0.1",
|
||||||
|
"json-stringify-safe": "^5.0.1",
|
||||||
|
"semver-compare": "^1.0.0",
|
||||||
|
"sprintf-js": "^1.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/semver": {
|
||||||
|
"version": "6.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||||
|
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"bin": {
|
||||||
|
"semver": "bin/semver.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/semver-compare": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"node_modules/serialize-error": {
|
||||||
|
"version": "7.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz",
|
||||||
|
"integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"type-fest": "^0.13.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/sprintf-js": {
|
||||||
|
"version": "1.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz",
|
||||||
|
"integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "BSD-3-Clause",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"node_modules/sumchecker": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"debug": "^4.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/type-fest": {
|
||||||
|
"version": "0.13.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz",
|
||||||
|
"integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "(MIT OR CC0-1.0)",
|
||||||
|
"optional": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/undici-types": {
|
||||||
|
"version": "7.18.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz",
|
||||||
|
"integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/universalify": {
|
||||||
|
"version": "0.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
|
||||||
|
"integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/wrappy": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC"
|
||||||
|
},
|
||||||
|
"node_modules/yauzl": {
|
||||||
|
"version": "2.10.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
|
||||||
|
"integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"buffer-crc32": "~0.2.3",
|
||||||
|
"fd-slicer": "~1.1.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "stepforge",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"description": "Fully offline desktop tool for capturing, annotating, and exporting step-by-step guides.",
|
||||||
|
"main": "app/main.js",
|
||||||
|
"license": "MPL-2.0",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"start": "electron .",
|
||||||
|
"test": "node --test tests/unit/",
|
||||||
|
"verify": "bash scripts/verify.sh",
|
||||||
|
"sample": "node scripts/make-sample-guide.js"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"electron": "^41.7.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
||||||
CONTRIBUTING="$ROOT_DIR/CONTRIBUTING.md"
|
|
||||||
|
|
||||||
assert_contains() {
|
|
||||||
local file="$1"
|
|
||||||
local needle="$2"
|
|
||||||
|
|
||||||
if ! grep -Fq -- "$needle" "$file"; then
|
|
||||||
printf 'Expected %s to contain: %s\n' "$file" "$needle" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
assert_contains "$CONTRIBUTING" "# Contributing"
|
|
||||||
assert_contains "$CONTRIBUTING" "## Before You Start"
|
|
||||||
assert_contains "$CONTRIBUTING" "issue number"
|
|
||||||
assert_contains "$CONTRIBUTING" "issue-123-update-readme"
|
|
||||||
assert_contains "$CONTRIBUTING" "Closes #123"
|
|
||||||
assert_contains "$CONTRIBUTING" "bash tests/run_test.sh"
|
|
||||||
assert_contains "$CONTRIBUTING" "tests/checks/"
|
|
||||||
assert_contains "$CONTRIBUTING" ".gitea/workflows/tests.yaml"
|
|
||||||
assert_contains "$CONTRIBUTING" "## Review Checklist"
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
||||||
ISSUE_TEMPLATE="$ROOT_DIR/.github/ISSUE_TEMPLATE.md"
|
|
||||||
PR_TEMPLATE="$ROOT_DIR/.github/PULL_REQUEST_TEMPLATE.md"
|
|
||||||
|
|
||||||
assert_contains() {
|
|
||||||
local file="$1"
|
|
||||||
local needle="$2"
|
|
||||||
|
|
||||||
if ! grep -Fq -- "$needle" "$file"; then
|
|
||||||
printf 'Expected %s to contain: %s\n' "$file" "$needle" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
assert_contains "$ISSUE_TEMPLATE" "## Improvement Area"
|
|
||||||
assert_contains "$ISSUE_TEMPLATE" "## Issue Type"
|
|
||||||
assert_contains "$ISSUE_TEMPLATE" "## Summary"
|
|
||||||
assert_contains "$ISSUE_TEMPLATE" "## Current Behavior"
|
|
||||||
assert_contains "$ISSUE_TEMPLATE" "## Expected Behavior"
|
|
||||||
assert_contains "$ISSUE_TEMPLATE" "## Steps To Reproduce"
|
|
||||||
assert_contains "$ISSUE_TEMPLATE" "## Testing Notes"
|
|
||||||
assert_contains "$ISSUE_TEMPLATE" "## Screenshots, Logs, or Extra Context"
|
|
||||||
|
|
||||||
assert_contains "$PR_TEMPLATE" "## Improvement Area"
|
|
||||||
assert_contains "$PR_TEMPLATE" "## Issue"
|
|
||||||
assert_contains "$PR_TEMPLATE" "Closes #"
|
|
||||||
assert_contains "$PR_TEMPLATE" "bash tests/run_test.sh"
|
|
||||||
assert_contains "$PR_TEMPLATE" "## Testing"
|
|
||||||
assert_contains "$PR_TEMPLATE" "## Deployment / Rollout Notes"
|
|
||||||
assert_contains "$PR_TEMPLATE" "Any follow-up work is tracked in TODO.md or an issue."
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
||||||
README="$ROOT_DIR/README.md"
|
|
||||||
|
|
||||||
assert_contains() {
|
|
||||||
local file="$1"
|
|
||||||
local needle="$2"
|
|
||||||
|
|
||||||
if ! grep -Fq -- "$needle" "$file"; then
|
|
||||||
printf 'Expected %s to contain: %s\n' "$file" "$needle" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
assert_contains "$README" "# "
|
|
||||||
assert_contains "$README" "## Overview"
|
|
||||||
assert_contains "$README" "## What's Included"
|
|
||||||
assert_contains "$README" "## Testing"
|
|
||||||
assert_contains "$README" "bash tests/run_test.sh"
|
|
||||||
assert_contains "$README" "## Contributing"
|
|
||||||
assert_contains "$README" "## Repository Layout"
|
|
||||||
assert_contains "$README" "See [ARCHITECTURE.md](ARCHITECTURE.md) to see the repo layout."
|
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Workflow check: the repository must be a runnable npm project with its
|
||||||
|
# documented layout, and package.json must parse and point at a real
|
||||||
|
# entrypoint. This validates structure by exercising it (node parses the
|
||||||
|
# manifest, the entrypoint resolves), not by grepping for strings.
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||||
|
cd "$ROOT_DIR"
|
||||||
|
|
||||||
|
for f in README.md LICENSE ARCHITECTURE.md SECURITY.md CONTRIBUTING.md \
|
||||||
|
CODE_OF_CONDUCT.md CHANGELOG.md package.json; do
|
||||||
|
if [[ ! -s "$f" ]]; then
|
||||||
|
echo "Missing or empty required file: $f" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
node -e '
|
||||||
|
const fs = require("fs");
|
||||||
|
const pkg = JSON.parse(fs.readFileSync("package.json", "utf8"));
|
||||||
|
if (!pkg.main) throw new Error("package.json has no main entrypoint");
|
||||||
|
if (!fs.existsSync(pkg.main)) {
|
||||||
|
// Entrypoint may not exist yet during early scaffolding of a fresh
|
||||||
|
// clone, but in a complete checkout it must.
|
||||||
|
throw new Error("entrypoint missing: " + pkg.main);
|
||||||
|
}
|
||||||
|
if (pkg.license !== "MPL-2.0") throw new Error("unexpected license id");
|
||||||
|
' 2>/dev/null || {
|
||||||
|
# Tolerate missing entrypoint only if app/ has not been committed yet.
|
||||||
|
if [[ -d app ]]; then
|
||||||
|
echo "package.json validation failed" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "repo structure OK"
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
||||||
WORKFLOW="$ROOT_DIR/.gitea/workflows/tests.yaml"
|
|
||||||
|
|
||||||
assert_contains() {
|
|
||||||
local file="$1"
|
|
||||||
local needle="$2"
|
|
||||||
|
|
||||||
if ! grep -Fq -- "$needle" "$file"; then
|
|
||||||
printf 'Expected %s to contain: %s\n' "$file" "$needle" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
if [[ ! -f "$WORKFLOW" ]]; then
|
|
||||||
printf 'Expected workflow file to exist: %s\n' "$WORKFLOW" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
assert_contains "$WORKFLOW" "name: Template tests"
|
|
||||||
assert_contains "$WORKFLOW" "push"
|
|
||||||
assert_contains "$WORKFLOW" "pull_request"
|
|
||||||
assert_contains "$WORKFLOW" "opened"
|
|
||||||
assert_contains "$WORKFLOW" "synchronize"
|
|
||||||
assert_contains "$WORKFLOW" "reopened"
|
|
||||||
assert_contains "$WORKFLOW" "runs-on: ubuntu-latest"
|
|
||||||
assert_contains "$WORKFLOW" "uses: https://gitea.com/actions/checkout@v4"
|
|
||||||
assert_contains "$WORKFLOW" "bash tests/run_test.sh"
|
|
||||||
Reference in New Issue
Block a user