Skip to content
Open
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
b1151a0
add more testing in preparation of refactors
ndelangen May 6, 2026
80ad549
adding the journey feature v0
ndelangen May 6, 2026
b28e63c
improve visual
ndelangen May 6, 2026
ce10849
fix(load): harden map parsing and presets for older saves
ndelangen May 6, 2026
809db11
add edit feature
ndelangen May 6, 2026
6a0796e
also allow markers and burgs to be points
ndelangen May 6, 2026
c6bc8af
simplify to existing "points" only
ndelangen May 6, 2026
6bf720e
add new campaign layer preset
ndelangen May 6, 2026
0151a42
allow styling of journey
ndelangen May 6, 2026
36de63a
fix initial campaign layer preset not rendering journey
ndelangen May 6, 2026
12e9b9b
cleanup
ndelangen May 7, 2026
1263053
cleanup
ndelangen May 7, 2026
ec8a6b4
Enhance readJourneyStyleConfig to preserve zero values for data attri…
ndelangen May 7, 2026
bedc404
Refactor journey resolution logic to introduce journeyResolvedStopEnt…
ndelangen May 7, 2026
728c6a4
Update journey insertion logic to position journeys below routes inst…
ndelangen May 7, 2026
a9ea014
Implement buildJourneyResolutionContext to enhance journey resolution…
ndelangen May 7, 2026
239541d
Refactor journey handling by introducing ensurePackJourneyNormalized …
ndelangen May 7, 2026
411627b
Refactor journey resolution context usage in JourneyDrawModule and jo…
ndelangen May 7, 2026
cf6d207
Update package versions and dependencies; refactor Playwright tests t…
ndelangen May 7, 2026
38ff8ea
Discard changes to package.json
ndelangen May 7, 2026
7090aad
Discard changes to tests/e2e/burgs.spec.ts
ndelangen May 7, 2026
9728b6a
Discard changes to tests/e2e/layers.spec.ts
ndelangen May 7, 2026
2e52940
Discard changes to tests/e2e/lakes-layer.spec.ts
ndelangen May 7, 2026
eb15e8a
Discard changes to tests/e2e/load-map.spec.ts
ndelangen May 7, 2026
45d5f4b
Discard changes to tests/e2e/states.spec.ts
ndelangen May 7, 2026
10cb526
Discard changes to tests/e2e/zones-export.spec.ts
ndelangen May 7, 2026
e2e51db
Discard changes to package-lock.json
ndelangen May 7, 2026
f9259d3
Refactor journey normalization logic to prioritize `stops[]` over leg…
ndelangen May 8, 2026
17c0809
Merge remote-tracking branch 'upstream/master' into norbert/campaign-…
ndelangen May 8, 2026
9242292
Update package-lock.json and package.json; refactor journey model to …
ndelangen May 8, 2026
fbbbe38
Discard changes to package.json
ndelangen May 8, 2026
f2dcf5a
Discard changes to package-lock.json
ndelangen May 8, 2026
5ead5b5
Refactor journey model tests to remove legacy handling of `stopIds` a…
ndelangen May 8, 2026
94e442f
Refactor journey-draw and journey-model modules to simplify type defi…
ndelangen May 8, 2026
b46d32b
simplify
ndelangen May 8, 2026
3594878
Refactor namesbase-editor and journey modules to utilize escapeHtml f…
ndelangen May 8, 2026
64ba9e6
Add editJourney method to global interface and import ensureEl utilit…
ndelangen May 8, 2026
112d4d5
Enhance type safety in journey module by explicitly defining the type…
ndelangen May 8, 2026
30c115c
allow for many Journeys
ndelangen May 8, 2026
8f59e57
linting & formatting
ndelangen May 8, 2026
86e7a09
delete normalization
ndelangen May 8, 2026
ad13398
linting & formatting
ndelangen May 8, 2026
22d49eb
Merge pull request #1 from ndelangen/norbert/multi-journey
ndelangen May 8, 2026
1be3ceb
improve gradient editing for journeys
ndelangen May 8, 2026
c2cf4da
Merge pull request #2 from ndelangen/norbert/improve-color-picking-jo…
ndelangen May 8, 2026
2ef737f
improve colors gradient display
ndelangen May 8, 2026
b6a6929
reduce commenting of code to adhere to repo standards
ndelangen May 8, 2026
1a21d24
reduce commenting of code to adhere to repo standards
ndelangen May 8, 2026
95d800e
improve arrow positioning
ndelangen May 8, 2026
1a682b5
ensure journey-legs never overlap, even when from different journeys
ndelangen May 8, 2026
58218e4
make naming more consistent
ndelangen May 8, 2026
fec0a79
Merge branch 'master' into norbert/campaign-journey
ndelangen May 8, 2026
5a8ee41
Merge branch 'norbert/campaign-journey' of github.com:ndelangen/Fanta…
ndelangen May 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,4 @@
"engines": {
"node": ">=24.0.0"
}
}
}
27 changes: 24 additions & 3 deletions playwright.config.ts
Comment thread
ndelangen marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,34 @@ import { defineConfig, devices } from '@playwright/test'
const isCI = !!process.env.CI
const skipBuild = !!process.env.SKIP_BUILD

/** Dedicated port avoids reuseExistingServer attaching to another project on the default Vite port. */
const devPort = process.env.PLAYWRIGHT_DEV_PORT ?? '5199'
const devOrigin = `http://127.0.0.1:${devPort}`
const previewOrigin = 'http://127.0.0.1:4173'
/** Matches vite.config.ts base (NETLIFY uses '/' for deploy previews). */
const appPath = process.env.NETLIFY ? '' : '/Fantasy-Map-Generator'
/** Trailing slash required so relative navigations resolve under the app path. */
const baseURL = appPath
? `${isCI ? previewOrigin : devOrigin}${appPath}/`
: `${isCI ? previewOrigin : devOrigin}/`

export default defineConfig({
testDir: './tests/e2e',
fullyParallel: true,
forbidOnly: isCI,
retries: 0,
workers: isCI ? 2 : undefined,
reporter: 'html',
expect: {
toHaveScreenshot: {
maxDiffPixels: 15000,
threshold: 0.25,
},
},
// Use OS-independent snapshot names (HTML content is the same across platforms)
snapshotPathTemplate: '{testDir}/{testFileDir}/{testFileName}-snapshots/{arg}{ext}',
use: {
baseURL: isCI ? 'http://localhost:4173' : 'http://localhost:5173',
baseURL,
trace: 'on-first-retry',
// Fixed viewport to ensure consistent map rendering
viewport: { width: 1280, height: 720 },
Expand All @@ -27,8 +44,12 @@ export default defineConfig({
webServer: {
// In CI: build (done as a separate cached step) and preview for production-like testing
// In dev: use vite dev server (faster, no rebuild needed)
command: isCI ? (skipBuild ? 'npm run preview' : 'npm run build && npm run preview') : 'npm run dev',
url: isCI ? 'http://localhost:4173' : 'http://localhost:5173',
command: isCI
? skipBuild
? 'npm run preview -- --host 127.0.0.1'
: 'npm run build && npm run preview -- --host 127.0.0.1'
: `npm run dev -- --host 127.0.0.1 --port ${devPort}`,
url: baseURL,
reuseExistingServer: !isCI,
timeout: 120000,
},
Expand Down
5 changes: 5 additions & 0 deletions public/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ let zones = viewbox.append("g").attr("id", "zones");
let borders = viewbox.append("g").attr("id", "borders");
let stateBorders = borders.append("g").attr("id", "stateBorders");
let provinceBorders = borders.append("g").attr("id", "provinceBorders");
let journeys = viewbox.append("g").attr("id", "journeys").style("display", "none");
let routes = viewbox.append("g").attr("id", "routes");
let roads = routes.append("g").attr("id", "roads");
let trails = routes.append("g").attr("id", "trails");
Expand Down Expand Up @@ -568,6 +569,9 @@ function invokeActiveZooming() {
const size = rn((10 / scale ** 0.3) * 2, 2);
ruler.selectAll("text").attr("font-size", size);
}

// journey layer: screen-constant sizing + LOD on tier change
if (layerIsOn("toggleJourney")) syncJourneyZoom(scale);
}

// add drag to upload logic, pull request from @evyatron
Expand Down Expand Up @@ -634,6 +638,7 @@ async function generate(options) {
else delete grid.cells.h;
grid.cells.h = await HeightmapGenerator.generate(grid);
pack = {}; // reset pack
pack.journey = {stops: []};

Features.markupGrid();
addLakesInDeepDepressions();
Expand Down
35 changes: 30 additions & 5 deletions public/modules/io/load.js
Original file line number Diff line number Diff line change
Expand Up @@ -164,11 +164,10 @@ async function parseLoadedResult(result) {
const isDelimited = resultAsString.substring(0, 10).includes("|");
let content = isDelimited ? resultAsString : decodeURIComponent(atob(resultAsString));

// fix if svg part has CRLF line endings instead of LF
const svgMatch = content.match(/<svg[^>]*id="map"[\s\S]*?<\/svg>/);
const svgContent = svgMatch[0];
const hasCrlfEndings = svgContent.includes("\r\n");
if (hasCrlfEndings) {
// fix if svg part has CRLF line endings instead of LF (some exports / old saves differ)
const svgMatch = content.match(/<svg[^>]*id="map"[\s\S]*?<\/svg>/i);
const svgContent = svgMatch?.[0];
if (svgContent?.includes("\r\n")) {
const correctedSvgContent = svgContent.replace(/\r\n/g, "\n");
content = content.replace(svgContent, correctedSvgContent);
}
Expand Down Expand Up @@ -357,6 +356,7 @@ async function parseLoadedData(data, mapVersion) {
anchors = icons.select("#anchors");
armies = viewbox.select("#armies");
markers = viewbox.select("#markers");
journeys = viewbox.select("#journeys");
ruler = viewbox.select("#ruler");
fogging = viewbox.select("#fogging");
debug = viewbox.select("#debug");
Expand All @@ -371,6 +371,9 @@ async function parseLoadedData(data, mapVersion) {
if (!emblems.size()) {
emblems = viewbox.insert("g", "#labels").attr("id", "emblems").style("display", "none");
}
if (!journeys.size()) {
journeys = viewbox.insert("g", "#ruler").attr("id", "journeys").style("display", "none");
Comment thread
ndelangen marked this conversation as resolved.
Outdated
}
}

{
Expand Down Expand Up @@ -413,6 +416,25 @@ async function parseLoadedData(data, mapVersion) {
// data[28] had deprecated cells.crossroad
pack.cells.routes = data[36] ? JSON.parse(data[36]) : {};
pack.ice = data[39] ? JSON.parse(data[39]) : [];
{
let parsedJourney = null;
if (data[40]) {
try {
parsedJourney = JSON.parse(data[40]);
} catch {
parsedJourney = null;
}
}
const j =
parsedJourney &&
typeof parsedJourney === "object" &&
parsedJourney !== null &&
!Array.isArray(parsedJourney)
? parsedJourney
: {stops: []};
pack.journey = j;
if (window.JourneyPack) window.JourneyPack.normalizePackJourney(pack.journey, pack);
}

if (data[31]) {
const namesDL = data[31].split("/");
Expand Down Expand Up @@ -464,6 +486,8 @@ async function parseLoadedData(data, mapVersion) {
if (isVisible(icons)) turnOn("toggleBurgIcons");
if (hasChildren(armies) && isVisible(armies)) turnOn("toggleMilitary");
if (hasChild(markers, "svg")) turnOn("toggleMarkers");
if (isVisible(journeys) && (hasChild(journeys, "path") || hasChild(journeys, "circle")))
turnOn("toggleJourney");
if (isVisible(ruler)) turnOn("toggleRulers");
if (isVisible(scaleBar)) turnOn("toggleScaleBar");
if (isVisibleNode(ensureEl("vignette"))) turnOn("toggleVignette");
Expand Down Expand Up @@ -735,6 +759,7 @@ async function parseLoadedData(data, mapVersion) {
// draw data layers (not kept in svg)
if (rulers && layerIsOn("toggleRulers")) rulers.draw();
if (layerIsOn("toggleGrid")) drawGrid();
if (layerIsOn("toggleJourney")) drawJourney();
}

{
Expand Down
4 changes: 3 additions & 1 deletion public/modules/io/save.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ function prepareMapData() {
const routes = JSON.stringify(pack.routes);
const zones = JSON.stringify(pack.zones);
const ice = JSON.stringify(pack.ice);
const journey = JSON.stringify(pack.journey || {stops: []});

// store name array only if not the same as default
const defaultNB = Names.getNameBases();
Expand Down Expand Up @@ -157,7 +158,8 @@ function prepareMapData() {
cellRoutes,
routes,
zones,
ice
ice,
journey
].join("\r\n");
return mapData;
}
Expand Down
3 changes: 2 additions & 1 deletion public/modules/ui/general.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ function showDataTip(event) {
if (!event.target) return;

let dataTip = event.target.dataset.tip;
if (!dataTip && event.target.parentNode.dataset.tip) dataTip = event.target.parentNode.dataset.tip;
if (!dataTip && event.target.parentNode?.dataset?.tip)
dataTip = event.target.parentNode.dataset.tip;
if (!dataTip) return;

const shortcut = event.target.dataset.shortcut;
Expand Down
1 change: 1 addition & 0 deletions public/modules/ui/hotkeys.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ function handleKeyup(event) {
else if ((shift || altShift) && code === "KeyV") overviewRivers();
else if ((shift || altShift) && code === "KeyM") overviewMilitary();
else if ((shift || altShift) && code === "KeyK") overviewMarkers();
else if ((shift || altShift) && code === "KeyJ") editJourney();
else if ((shift || altShift) && code === "KeyE") viewCellDetails();
else if (key === "!") toggleAddBurg();
else if (key === "@") toggleAddLabel();
Expand Down
Loading
Loading