Release v1.61.0-beta.2 candidate

This commit is contained in:
Matysh
2026-08-10 00:24:42 +03:00
parent 112c260314
commit fb382bfa11
49 changed files with 6342 additions and 1509 deletions
File diff suppressed because it is too large Load Diff
+20
View File
@@ -0,0 +1,20 @@
import test from 'node:test';
import assert from 'node:assert/strict';
import { screenRgb, svgScreenBlendSupported } from '../test-build/glow-blend.js';
test('screenRgb implements rounded 8-bit screen blending', () => {
assert.deepEqual(screenRgb([0, 0, 0], [12, 34, 56]), [12, 34, 56]);
assert.deepEqual(screenRgb([255, 10, 20], [8, 255, 30]), [255, 255, 48]);
assert.deepEqual(screenRgb([128, 32, 16], [16, 64, 128]), [136, 88, 136]);
});
test('capability result is one cached Promise per document', async () => {
const document = {
defaultView: { CSS: { supports: () => false } },
};
const first = svgScreenBlendSupported(document);
const second = svgScreenBlendSupported(document);
assert.equal(first, second);
assert.equal(await first, false);
});
+22
View File
@@ -0,0 +1,22 @@
import test from 'node:test';
import assert from 'node:assert/strict';
import { readFileSync } from 'node:fs';
const load = () => JSON.parse(readFileSync(
new URL('./fixtures/glow/additive-pools.json', import.meta.url), 'utf8',
));
test('shared additive Glow fixture is deterministic and covers 1/10/30/60 pools', () => {
const fixture = load();
assert.equal(fixture.fixture, 'additive-pools-v1');
assert.deepEqual(fixture.variants, [1, 10, 30, 60]);
assert.equal(fixture.config.spaces[0].rooms.length, 2);
assert.equal(fixture.config.spaces[0].walls.length > 0, true);
assert.equal(fixture.config.spaces[0].openings.length > 0, true);
assert.equal(fixture.config.markers.length, 60);
assert.equal(Object.keys(fixture.layout).length, 60);
assert.equal(Object.keys(fixture.ha.states).length, 60);
assert.equal(new Set(fixture.config.markers.map((marker) => marker.id)).size, 60);
assert.equal(JSON.stringify(load()), JSON.stringify(fixture));
});
+14 -1
View File
@@ -11,7 +11,7 @@ import {
alignGuides, segmentAngle, is45,
swipeTarget, clampScale,
migratePdfUrls,
roomFillModeOf,
roomFillModeOf, roomGlowOf,
contentUrl, chunk, referencedContentUrls, MAX_SIGN_PATHS,
interiorPoint,
segmentCm, formatLength, roomEdges, roomPoly, paperRoomShapes, pointOnBoundary, pointStrictlyInside, roomsOverlap,
@@ -260,6 +260,7 @@ test('spaceDisplayOf: defaults differ for spaces with and without a plan', () =>
assert.equal(withPlan.showBorders, false);
assert.equal(withPlan.showNames, false);
assert.equal(withPlan.fill, 'none');
assert.equal(withPlan.glow, false);
const noPlan = spaceDisplayOf({ plan_url: null });
assert.equal(noPlan.showBorders, true);
assert.equal(noPlan.showNames, true);
@@ -271,6 +272,11 @@ test('spaceDisplayOf: defaults differ for spaces with and without a plan', () =>
const g = spaceDisplayOf({ settings: { room_color: 'javascript:alert(1)', fill_mode: 'weird' } });
assert.equal(g.color, '#55606c'); // dark-grey default since 2026-08-03
assert.equal(g.fill, 'none');
assert.equal(g.glow, false);
const legacyGlow = spaceDisplayOf({ settings: { fill_mode: 'glow' } });
assert.deepEqual({ fill: legacyGlow.fill, glow: legacyGlow.glow }, { fill: 'none', glow: true });
const explicitOff = spaceDisplayOf({ settings: { fill_mode: 'glow', glow_enabled: false } });
assert.deepEqual({ fill: explicitOff.fill, glow: explicitOff.glow }, { fill: 'none', glow: false });
});
test('spaceDisplayOf: the two hide switches are opt-in and strictly boolean', () => {
@@ -1033,6 +1039,13 @@ test('roomFillModeOf: tier-3 override beats the space, junk inherits', () => {
assert.equal(roomFillModeOf('temp', { settings: { fill_mode: 'glow' } }), 'temp'); // glow нельзя выбрать per-room
});
test('roomGlowOf: explicit room data wins legacy and space fallbacks', () => {
assert.equal(roomGlowOf(false, { settings: { fill_mode: 'glow' } }), true);
assert.equal(roomGlowOf(true, { settings: { fill_mode: 'glow', glow: false } }), false);
assert.equal(roomGlowOf(false, { settings: { glow: true } }), true);
assert.equal(roomGlowOf(true, { settings: { fill_mode: 'temp' } }), true);
});
test('splitRoomPath: both ends on the SAME edge carve a niche (audit G1)', () => {
const sq = [[0, 0], [10, 0], [10, 10], [0, 10]];
const A = (p) => Math.round(polygonArea(p) * 1000) / 1000;
+25
View File
@@ -168,6 +168,31 @@ test('optimizer repairs legacy cell_cm values into the server schema range', ()
assert.equal(result.report.migrated, 6);
});
test('optimizer separates legacy Glow from data fill without losing explicit booleans', () => {
const result = optimizePlans({
spaces: [{
id: 'legacy', title: 'Legacy', view_box: [0, 0, 1, 1],
settings: { fill_mode: 'glow', glow_enabled: false, future: 'kept' },
rooms: [
{ ...room('a', 0, 0.5), settings: { fill_mode: 'glow', future: 1 } },
{ ...room('b', 0.5, 1), settings: { fill_mode: 'glow', glow: false } },
],
}],
markers: [], settings: {},
}, {});
const space = result.config.spaces[0];
assert.equal(space.settings.fill_mode, 'none');
assert.equal(space.settings.glow_enabled, false);
assert.equal(space.settings.future, 'kept');
assert.deepEqual(space.rooms[0].settings, { future: 1, glow: true });
assert.deepEqual(space.rooms[1].settings, { glow: false });
assert.equal(result.report.migrated, 3);
assert.equal(result.report.glowSpacesMigrated, 1);
assert.equal(result.report.glowRoomsMigrated, 2);
const again = optimizePlans(result.config, result.layout);
assert.equal(again.changed, false);
});
test('optimizer canonicalises only an explicitly stored square-column angle', () => {
const result = optimizePlans({
spaces: [{