Skip to content

WIP: Add website contribution workflow#108

Merged
AussieScorcher merged 1 commit into
mainfrom
feat/contribution-generator
Jul 17, 2026
Merged

WIP: Add website contribution workflow#108
AussieScorcher merged 1 commit into
mainfrom
feat/contribution-generator

Conversation

@AussieScorcher

@AussieScorcher AussieScorcher commented Jul 17, 2026

Copy link
Copy Markdown
Member

Summary

Adds an end-to-end website contribution workflow that builds draft BARS XML from locally selected scenery packages. Extraction and matching run client-side in a Web Worker, so scenery files are not uploaded to an application endpoint.

Changes Made

  • Added browser-side scenery package extraction, classification, geometry matching, selective removals, and draft XML generation.
  • Reworked the XML generator and contribution pages to support local package selection, progress/error states, downloads, and contribution-policy handling.
  • Added map diagnostics for simulator geometry, Division data, and unmatched objects, plus matching tests and required Vite/ESLint configuration.

Additional Information

  • User impact: contributors can generate a safer first-pass XML draft from installed scenery and review unmatched or unsafe objects manually.
  • Validation: git diff --check passed. pnpm test, pnpm lint, and pnpm build could not complete because the existing node_modules mixed package-manager state left vite.exe locked; pnpm dependency repair then failed during automatic registry access.

Author Information

Discord Username:
VATSIM CID: 1658308


Checklist:

  • Have you followed the guidelines in our Contributing document?
  • Have you checked to ensure there aren't other open Pull Requests for the same update/change?

@AussieScorcher
AussieScorcher marked this pull request as ready for review July 17, 2026 12:18
Comment thread src/features/draft-generator/extractor/classify.js Dismissed
}
const thresholdAlong = end === "primary" ? primaryThresholdAlong : secondaryThresholdAlong;
const direction = end === "primary" ? 1 : -1;
const threshold = end === "primary" ? primaryThreshold : secondaryThreshold;
return runwayZone(runway, lightType, "Point", { point }, extra);
}

function runwayPolygonZone(runway, lightType, vertices, extra = {}) {
@AussieScorcher
AussieScorcher merged commit 18ae24b into main Jul 17, 2026
6 checks passed
@AussieScorcher
AussieScorcher deleted the feat/contribution-generator branch July 17, 2026 12:20
@greptile-apps

greptile-apps Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR introduces a full client-side draft BARS XML generator: a Web Worker reads locally selected scenery packages (.bgl and XML files) via virtual filesystem shims that map node: built-ins to browser-compatible implementations, runs geometric matching against Division BARS data, and produces a downloadable draft XML and diagnostic GeoJSON — without uploading any files to a server. ContributeTest is wired to accept the resulting XML via router state, and the contribution map and test pages gain contribution-policy awareness.

  • New core modules: draft-generator.worker.js, extractor/bgl.js (~2100 lines of BGL binary parser), extractor/extract.js, matching.js (~2300 lines), draft-output.js, and browser shims for buffer, crypto, fs, and path, plus DraftGeneratorMap.jsx for result diagnostics.
  • XMLGenerator.jsx rework: proper AbortController on API fetches, worker lifecycle management with unique request IDs, object URL cleanup, and policy gating with a DEV-mode bypass.
  • ContributeTest.jsx: accepts incoming draft XML from router state to pre-populate the upload zone, adds a "Draft" breadcrumb step, and initialises file-size state via a redundant Blob calculation.

Confidence Score: 4/5

Safe to continue iterating on; no data-loss or correctness defects found in the core generation pipeline.

The new generation pipeline (worker, virtual FS, BGL parser, matching engine, XML output) is architecturally clean and the Worker lifecycle is handled correctly in XMLGenerator.jsx. The three findings are all non-blocking quality issues: a misleading breadcrumb when skipping the Draft step, a redundant Blob size calculation, and blanket ESLint exclusion of the most complex files. Given this is explicitly a WIP/draft PR, these are reasonable to address before merging.

eslint.config.js (blanket extractor ignore removes lint coverage from bgl.js and extract.js), src/pages/ContributeTest.jsx (unconditional Draft breadcrumb and redundant Blob initialiser).

Important Files Changed

Filename Overview
src/features/draft-generator/draft-generator.worker.js New Web Worker entry point; clean lifecycle management with per-request ID tracking, proper error propagation, and virtual-FS mount/unmount in a finally block.
src/features/draft-generator/extractor/bgl.js New 2096-line BGL parser; structurally sound, uses shimmed Node.js APIs correctly, and manages a two-pass buffer retention budget for browser memory constraints. No ESLint coverage due to ignore config.
src/features/draft-generator/shims/virtual-fs.js In-memory virtual filesystem shim wrapping browser File objects; correctly implements stat, readdir, readFile, writeFile, createReadStream, and mkdir with proper ENOENT errors.
src/features/draft-generator/shims/crypto.js Browser SHA-1 shim used only for string-based stable IDs; since stableId always converts inputs to strings before hashing, the implementation is consistent with Node.js behavior.
src/features/draft-generator/local-package.js File selection from input, drag-and-drop (modern FileSystemHandle and legacy WebkitEntry APIs), and path normalization; only includes File objects for .bgl and .xml extensions, which is correct.
src/pages/XMLGenerator.jsx Reworked generator page with proper worker lifecycle, AbortController for API fetches, policy gating, progress reporting, and object URL management with useEffect cleanup.
src/pages/ContributeTest.jsx Now accepts incoming draft XML from router state; unconditional "Draft" breadcrumb item may mislead users who arrive directly from Map; originalFileSize Blob initializer is redundant.
src/pages/ContributeMap.jsx Minor additions: draftGeneratorDisabled computed value with DEV-mode override, Draft Generator button, and development hint in disabled-policy banner; existing code unchanged.
eslint.config.js Added ignore patterns for extractor/ and shims/ to avoid false positives from node: imports, but removes all ESLint coverage from the most complex parsing files in the PR.
vite.config.ts Adds four resolve aliases mapping node: built-ins to browser shims; straightforward and correct for enabling Node-style imports in the Vite/browser build.
src/features/draft-generator/matching.js New 2310-line geometric matching engine with complex scoring, partition, and containment logic; logically structured with clear TYPE_CONFIG constants and well-named helpers.
Prompt To Fix All With AI
Fix the following 3 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 3
eslint.config.js:10-13
**Blanket ignore removes lint coverage from complex parsing code**

The extractor and shims directories are excluded entirely to avoid false positives from `node:` imports, but this also removes ESLint coverage from the most complex files in the PR (`bgl.js` at ~2100 lines, `extract.js` at ~2150 lines). A narrower fix would configure a second config entry for those directories with `globals.node` added — that suppresses the browser-globals false positives while still catching undefined variables, dead code, and logic errors in the binary parsing routines.

### Issue 2 of 3
src/pages/ContributeTest.jsx:305-309
**"Draft" breadcrumb shown regardless of navigation path**

The `Draft` breadcrumb item is now always rendered on the Test page. When a user reaches the Test page via the Map's "Continue to Next Step" button (which navigates directly to `/contribute/test/${icao}`), the breadcrumb incorrectly shows a Draft Generator step the user never visited. The breadcrumb trail becomes Airport → Map → **Draft** → Test even though the user's actual path was Airport → Map → Test. Consider conditionally rendering this item only when `location.state?.draftXml` is present (i.e., the user actually came from the generator).

### Issue 3 of 3
src/pages/ContributeTest.jsx:44-46
**`originalFileSize` initializer is dead code**

`originalFileSize` is initialised with `new Blob([incomingDraftXml]).size`, but that value is immediately overwritten inside `handleTestXml` with `selectedFile.size` on a successful validation response (and the state is never read before the first test completes). The Blob allocation is wasted work. Since `selectedFile` is already initialised to `new File([incomingDraftXml], ...)`, the initial value could simply be `incomingDraftXml ? new File([incomingDraftXml], incomingDraftFileName, { type: 'application/xml' }).size : 0` — or just `0` — with no observable difference.

Reviews (1): Last reviewed commit: "feat: add website contribution workflow" | Re-trigger Greptile

Comment thread eslint.config.js
Comment on lines +10 to +13
'dist',
'src/features/draft-generator/extractor/**',
'src/features/draft-generator/shims/**',
],

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Blanket ignore removes lint coverage from complex parsing code

The extractor and shims directories are excluded entirely to avoid false positives from node: imports, but this also removes ESLint coverage from the most complex files in the PR (bgl.js at ~2100 lines, extract.js at ~2150 lines). A narrower fix would configure a second config entry for those directories with globals.node added — that suppresses the browser-globals false positives while still catching undefined variables, dead code, and logic errors in the binary parsing routines.

Prompt To Fix With AI
This is a comment left during a code review.
Path: eslint.config.js
Line: 10-13

Comment:
**Blanket ignore removes lint coverage from complex parsing code**

The extractor and shims directories are excluded entirely to avoid false positives from `node:` imports, but this also removes ESLint coverage from the most complex files in the PR (`bgl.js` at ~2100 lines, `extract.js` at ~2150 lines). A narrower fix would configure a second config entry for those directories with `globals.node` added — that suppresses the browser-globals false positives while still catching undefined variables, dead code, and logic errors in the binary parsing routines.

How can I resolve this? If you propose a fix, please make it concise.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Comment on lines 305 to 309
<Breadcrumb>
<BreadcrumbItem title="Airport" link="/contribute/new" />
<BreadcrumbItem title="Map" link={`/contribute/map/${icao}`} />
<BreadcrumbItem title="Draft" link={`/contribute/generator/${icao}`} />
<BreadcrumbItem title="Test" />

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 "Draft" breadcrumb shown regardless of navigation path

The Draft breadcrumb item is now always rendered on the Test page. When a user reaches the Test page via the Map's "Continue to Next Step" button (which navigates directly to /contribute/test/${icao}), the breadcrumb incorrectly shows a Draft Generator step the user never visited. The breadcrumb trail becomes Airport → Map → Draft → Test even though the user's actual path was Airport → Map → Test. Consider conditionally rendering this item only when location.state?.draftXml is present (i.e., the user actually came from the generator).

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/pages/ContributeTest.jsx
Line: 305-309

Comment:
**"Draft" breadcrumb shown regardless of navigation path**

The `Draft` breadcrumb item is now always rendered on the Test page. When a user reaches the Test page via the Map's "Continue to Next Step" button (which navigates directly to `/contribute/test/${icao}`), the breadcrumb incorrectly shows a Draft Generator step the user never visited. The breadcrumb trail becomes Airport → Map → **Draft** → Test even though the user's actual path was Airport → Map → Test. Consider conditionally rendering this item only when `location.state?.draftXml` is present (i.e., the user actually came from the generator).

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +44 to +46
const [originalFileSize, setOriginalFileSize] = useState(() =>
incomingDraftXml ? new Blob([incomingDraftXml]).size : 0
);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 originalFileSize initializer is dead code

originalFileSize is initialised with new Blob([incomingDraftXml]).size, but that value is immediately overwritten inside handleTestXml with selectedFile.size on a successful validation response (and the state is never read before the first test completes). The Blob allocation is wasted work. Since selectedFile is already initialised to new File([incomingDraftXml], ...), the initial value could simply be incomingDraftXml ? new File([incomingDraftXml], incomingDraftFileName, { type: 'application/xml' }).size : 0 — or just 0 — with no observable difference.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/pages/ContributeTest.jsx
Line: 44-46

Comment:
**`originalFileSize` initializer is dead code**

`originalFileSize` is initialised with `new Blob([incomingDraftXml]).size`, but that value is immediately overwritten inside `handleTestXml` with `selectedFile.size` on a successful validation response (and the state is never read before the first test completes). The Blob allocation is wasted work. Since `selectedFile` is already initialised to `new File([incomingDraftXml], ...)`, the initial value could simply be `incomingDraftXml ? new File([incomingDraftXml], incomingDraftFileName, { type: 'application/xml' }).size : 0` — or just `0` — with no observable difference.

How can I resolve this? If you propose a fix, please make it concise.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants