From 3bc89b74169ebd163a61949035f2aa091f7be4ae Mon Sep 17 00:00:00 2001 From: Keiichiro Ui Date: Sun, 12 Jul 2026 15:30:37 +0900 Subject: [PATCH] Audit src/worker/ comments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase 2 for #225. All four worker files, 111 flagged comments. src/worker/ now fully audited. Field-level and function-level rationale moved to JSDoc across the map renderer (allPrefabs, tileIndex cache, composite cache/mirror, generation counter, drawPrefabFootprints preamble, withAlpha, anchorOffset, PNG_HEADER_BYTES) and the filter worker (PrefabsFilterOutputMessage protocol, tryCompileRegex, matchAndHighlight). In-body design decisions kept as WHY: / INVARIANT: markers: - map-renderer: compose-before-canvas-resize timing; Path2D batching motivated by a Chrome CrGpuMain trace; canvas y-inversion; footprint stroke inset; resetTransform for 1:1 sprite stamps; reversed z-ordering iteration; radiation full-brightness; footprints inside cached composite; static-lookup reference identity in cache key; per-layer bitmap release on close. - prefab-filter: streaming staleness INVARIANT; detached streamChunks; matched-block-cap accounting INVARIANT; SW-corner half-extent shift for distance. - worker/map-renderer: shared glyph fetch memoisation; OffscreenCanvas first-message capture INVARIANT; message queue for serialised handling; non-awaited update to let throttledInvoker coalesce. - worker/prefabs-filter: bumpInputVersion ordering rationale. Style: single-clause sentences using because / so / since for causation, no ; / — / colon-elaboration per the #235-#236 memo. EXCLUDED_PATHS shrinks from 30 to 26. --- src/worker/lib/map-renderer.ts | 150 ++++++++---------- src/worker/lib/prefab-filter.ts | 38 ++--- src/worker/map-renderer.ts | 13 +- src/worker/prefabs-filter.ts | 2 +- .../lint-plugins/require-comment-rationale.ts | 4 - 5 files changed, 92 insertions(+), 115 deletions(-) diff --git a/src/worker/lib/map-renderer.ts b/src/worker/lib/map-renderer.ts index a3fcf556..2d1f166d 100644 --- a/src/worker/lib/map-renderer.ts +++ b/src/worker/lib/map-renderer.ts @@ -28,16 +28,22 @@ export default class MapRenderer { markerCoords: GameCoords | null = null; scale = 0.1; filteredPrefabs: Prefab[] = []; - // Full decoration list straight from prefabs.xml — drives the footprint - // overlay and tile-district lookup regardless of the filter state. + /** + * Full decoration list straight from `prefabs.xml`. Drives the + * footprint overlay and tile-district lookup regardless of the + * filter state. + */ allPrefabs: Prefab[] = []; - // Cache of the tile index keyed by the most recent `allPrefabs` reference, - // so the index is rebuilt only when the upstream array changes. + /** + * Cache of the tile index keyed by the most recent `allPrefabs` + * reference so the index is rebuilt only when the upstream array + * changes. + */ #tileIndex: { source: Prefab[]; index: TileIndex } | null = null; #meshSizesHolder: CacheHolder; #densityScoresHolder: CacheHolder; #districtColorsHolder: CacheHolder; - // On-screen glyph size in output pixels, independent of the map scale. + /** On-screen glyph size in output pixels, independent of the map scale. */ prefabSignSize = 20; prefabSignAlpha = 1; prefabFootprintAlpha = 1; @@ -47,8 +53,10 @@ export default class MapRenderer { radAlpha = 1; canvas: OffscreenCanvas; - // Mirror of the sign/marker-free composite, kept for the terrain viewer - // which samples its placeholder canvas element as a texture. + /** + * Mirror of the sign/marker-free composite, kept for the terrain + * viewer which samples its placeholder canvas element as a texture. + */ compositeCanvas: OffscreenCanvas | null = null; #signPath2D: Path2D; #signAnchor: GlyphMarker["anchor"]; @@ -60,14 +68,19 @@ export default class MapRenderer { { width: number; height: number } >(); - // Composited base map (layers + brightness + per-layer alpha + footprint - // overlay) cached so that sign/marker-only updates can skip recompositing. + /** + * Composited base map (layers, brightness, per-layer alpha, footprint + * overlay) cached so sign/marker-only updates can skip recompositing. + */ #composite: OffscreenCanvas | null = null; #compositeKey: string | null = null; - // Reference identity of the `allPrefabs` array that produced the cached - // composite; bumped implicitly when the upstream array is replaced. + /** + * Reference identity of the `allPrefabs` array that produced the + * cached composite. Bumped implicitly when the upstream array is + * replaced. + */ #compositeAllPrefabs: Prefab[] | null = null; - // Bumped whenever a source image is invalidated, to invalidate the composite. + /** Bumped whenever a source image is invalidated to invalidate the composite. */ #generation = 0; constructor( @@ -83,9 +96,7 @@ export default class MapRenderer { this.#signAnchor = signMarker.anchor; this.#markPath2D = new Path2D(markMarker.d); this.#markAnchor = markMarker.anchor; - // Static tables fetched on demand inside the worker, mirroring the - // CacheHolder usage in PrefabFilter. The deconstructor is a no-op - // because nothing here owns external resources. + // WHY: static tables are fetched on demand inside the worker, mirroring PrefabFilter's CacheHolder usage. The deconstructor is a no-op because nothing here owns external resources. const noop = () => {}; this.#meshSizesHolder = new CacheHolder(fetchMeshSizes, noop); this.#densityScoresHolder = new CacheHolder(fetchDensityScores, noop); @@ -116,8 +127,7 @@ export default class MapRenderer { if (width === 0 || height === 0) { this.canvas.width = 1; this.canvas.height = 1; - // This path skips #composeBase, so the mirror must be cleared here or - // the previous map would linger in the terrain viewer. + // WHY: this path skips #composeBase, so the mirror must be cleared here or the previous map would linger in the terrain viewer. if (this.compositeCanvas) { this.compositeCanvas.width = 1; this.compositeCanvas.height = 1; @@ -131,20 +141,13 @@ export default class MapRenderer { const context = this.canvas.getContext("2d"); if (!context) throw new Error("Failed to get 2d context"); - // Static lookup tables are fetched lazily inside the worker. Their values - // never change between map loads so they are cheap to re-fetch (the - // CacheHolder amortises to a no-op after the first call). const [meshSizes, districtColors, densityScores] = await Promise.all([ this.#meshSizesHolder.get(), this.#districtColorsHolder.get(), this.#densityScoresHolder.get(), ]); - // Compose the base map + footprint overlay (which may re-decode at the - // new size) before touching the visible canvas. Resizing the canvas - // clears it, so doing it ahead of an await would expose a blank canvas - // and cause a flash while scaling; instead we resize and redraw in one - // synchronous pass below. + // WHY: compose the base map and footprint overlay before touching the visible canvas. Resizing the canvas clears it, so doing that ahead of an await would flash a blank canvas while scaling. Resize and redraw run in one synchronous pass below. const base = await this.#composeBase( canvasWidth, canvasHeight, @@ -159,8 +162,7 @@ export default class MapRenderer { context.imageSmoothingEnabled = false; if (base) context.drawImage(base, 0, 0); - // Sign + marker overlays sit on top of the cached composite and are - // redrawn every paint so filter / flag interactions stay responsive. + // WHY: sign and marker overlays sit on top of the cached composite and are redrawn every paint so filter and flag interactions stay responsive. context.save(); context.scale(this.scale, this.scale); if (this.prefabSignAlpha > 0) { @@ -173,12 +175,15 @@ export default class MapRenderer { context.restore(); } - // Draw each prefab as a rotated rectangle sized by PrefabSize. Drawn under - // the ✘ marker so the filter highlight remains visible on top. Mirrors the - // game's PrefabPreviewManager: skip `rwg_tile*` (the placement framework - // itself) and `part_driveway*` (sub-parts that overlap their parent POI). - // Per-POI colour matches the in-game preview: it comes from the tile that - // contains the POI, with name- and DensityScore-based modifiers applied. + /** + * Draws each prefab as a rotated rectangle sized by `PrefabSize`. + * Rendered under the ✘ marker so the filter highlight stays visible + * on top. Mirrors the game's `PrefabPreviewManager` by skipping + * `rwg_tile*` (the placement framework) and `part_driveway*` + * (sub-parts that overlap their parent POI). Per-POI colour matches + * the in-game preview, sourced from the tile that contains the POI + * with name- and DensityScore-based modifiers applied. + */ #drawPrefabFootprints( context: OffscreenCanvasRenderingContext2D, width: number, @@ -189,19 +194,13 @@ export default class MapRenderer { ) { const offsetX = width / 2; const offsetY = height / 2; - // Outline thickness in game-block units (the renderer's current transform - // scales it down to canvas pixels). Drawn inset by `stroke / 2` further - // below so two neighbours sharing an edge never double-stroke. + // WHY: outline thickness is in game-block units because the renderer's transform scales it to canvas pixels. Drawn inset by stroke/2 below so two neighbours sharing an edge never double-stroke. const stroke = 8; const half = stroke / 2; const tileIndex = this.#getTileIndex(); - // Batch fill and stroke rects by color into Path2D objects so each unique - // color requires only two GPU draw calls (fill + stroke) instead of one - // pair per prefab. A Chrome trace showed CrGpuMain tasks of 300–865 ms - // during footprint redraws (~10 k ops for 1000 prefabs), stalling the - // compositor and causing visible slider stutter. + // WHY: batch fill and stroke rects by colour into Path2D objects so each unique colour costs only one fill and one stroke draw call. A Chrome trace showed CrGpuMain tasks of 300 to 865 ms during footprint redraws with per-prefab calls, stalling the compositor. const fillPaths = new Map(); const strokePaths = new Map(); @@ -213,15 +212,13 @@ export default class MapRenderer { const size = meshSizes[prefab.name]; if (!size) continue; const [sx, sz] = size; - // decoration.position is the SW corner of the rotated AABB, so for - // 90°/270° rotations the world-aligned width/depth swap. No canvas - // rotation is needed because the bounding box stays axis-aligned. + // WHY: decoration.position is the SW corner of the rotated AABB, so rotations by 90° or 270° swap the world-aligned width and depth. The bounding box stays axis-aligned, so no canvas rotation is needed. const odd = ((prefab.rotation ?? 0) & 1) === 1; const w = odd ? sz : sx; const d = odd ? sx : sz; const cx = offsetX + prefab.x; - // prefab vertical positions are inverted for canvas coordinates + // WHY: prefab vertical positions run north-positive but canvas y runs down. const cy = offsetY - prefab.z; const color = footprintColorHex( @@ -239,11 +236,7 @@ export default class MapRenderer { } fp.rect(cx, cy - d, w, d); - // Canvas strokes straddle the path, so an N-block outline would spill - // N/2 blocks past the prefab edge and double-up where neighbours share - // a boundary. Inset by half the stroke so the outer edge sits exactly - // on the prefab boundary, then clamp negatives for prefabs smaller - // than the stroke (very rare; they collapse to a point). + // WHY: canvas strokes straddle the path, so an N-block outline would spill N/2 blocks past the prefab edge and double up where neighbours share a boundary. Inset by half the stroke so the outer edge sits on the prefab boundary. Clamp negatives for prefabs smaller than the stroke, which collapse to a point. const iw = Math.max(0, w - stroke); const id = Math.max(0, d - stroke); let sp = strokePaths.get(color); @@ -266,7 +259,7 @@ export default class MapRenderer { } } - // Cached wrapper over buildTileIndex; rebuilt only when allPrefabs changes. + /** Cached wrapper over `buildTileIndex`. Rebuilds only when `allPrefabs` changes. */ #getTileIndex(): TileIndex { if (this.#tileIndex && this.#tileIndex.source === this.allPrefabs) { return this.#tileIndex.index; @@ -303,9 +296,7 @@ export default class MapRenderer { this.prefabFootprintAlpha, this.#generation, ].join(":"); - // The static lookup tables are pinned for the lifetime of the worker, so - // their reference identity is enough; allPrefabs is replaced on every - // prefabs.xml load and is the only input that escapes the key string. + // WHY: the static lookup tables are pinned for the lifetime of the worker, so their reference identity is enough. allPrefabs is replaced on every prefabs.xml load and is the only input that escapes the key string. if ( this.#composite && this.#compositeKey === key && @@ -343,15 +334,12 @@ export default class MapRenderer { context.drawImage(splat4, 0, 0); } if (rad && this.radAlpha !== 0) { - // Radiation is intentionally drawn at full brightness so its tint - // stays readable on dimmed maps. + // WHY: radiation is drawn at full brightness so its tint stays readable on dimmed maps. context.filter = "none"; context.globalAlpha = this.radAlpha; context.drawImage(rad, 0, 0); } - // Footprints go inside the cached composite so the brightness filter - // applies the same way it does to the biomes/splat layers, and so - // sign-only re-renders don't have to recompute them. + // WHY: footprints go inside the cached composite so the brightness filter applies the same way it does to the biomes and splat layers, and so sign-only re-renders skip recomputing them. if (this.prefabFootprintAlpha > 0) { context.save(); context.filter = `brightness(${this.brightness})`; @@ -368,15 +356,14 @@ export default class MapRenderer { context.restore(); } } finally { - // Only the composite is cached; release the per-layer bitmaps. + // WHY: only the composite is cached, so release the per-layer bitmaps here. for (const bitmap of [biomes, splat3, splat4, rad]) bitmap?.close(); } this.#composite = canvas; this.#compositeKey = key; this.#compositeAllPrefabs = this.allPrefabs; - // Copying only on recompose keeps the mirror current: cache hits mean - // the composite content is unchanged. + // WHY: copy only on recompose to keep the mirror current because cache hits mean the composite content is unchanged. if (this.compositeCanvas) { this.compositeCanvas.width = width; this.compositeCanvas.height = height; @@ -407,25 +394,21 @@ export default class MapRenderer { signSize, ); - // Remove the active scale transform so the sprite stamps 1:1 on output - // pixels. globalAlpha set by the caller is unaffected by resetTransform. + // WHY: remove the active scale transform so the sprite stamps 1:1 on output pixels. globalAlpha set by the caller is unaffected by resetTransform. context.save(); context.resetTransform(); - // Inverted iteration to overwrite signs by higher order prefabs + // WHY: iterate reversed so higher-order prefabs overwrite lower ones. for (const prefab of this.filteredPrefabs.toReversed()) { - // decoration.position is the SW corner of the rotated AABB; shift to - // the centre so the ✘ marks the middle of the footprint. Falls back to - // a zero-size offset when the mesh size is unknown. + // WHY: decoration.position is the SW corner of the rotated AABB. Shift to the centre so the ✘ marks the middle of the footprint. Falls back to a zero offset when the mesh size is unknown. const meshSize = meshSizes[prefab.name]; const odd = ((prefab.rotation ?? 0) & 1) === 1; const halfW = meshSize ? (odd ? meshSize[1] : meshSize[0]) / 2 : 0; const halfD = meshSize ? (odd ? meshSize[0] : meshSize[1]) / 2 : 0; const x = offsetX + prefab.x + halfW; - // prefab vertical positions are inverted for canvas coordinates + // WHY: prefab vertical positions run north-positive but canvas y runs down. const z = offsetY - prefab.z - halfD; - // Multiply by scale to convert game-world coords to canvas pixels; the - // anchor offset is already in output pixels so it applies after scaling. + // WHY: multiply by scale to convert game-world coords to canvas pixels. The anchor offset is already in output pixels and applies after scaling. context.drawImage( sprite, Math.round(x * scale + charOffsetX - spriteCX), @@ -513,9 +496,11 @@ export default class MapRenderer { } } -// Build an `rgba(r, g, b, a)` string from a `#rrggbb` colour. Falls back to -// the input when the hex format is unrecognised so the renderer still gets a -// valid CSS colour for the stroke pass. +/** + * Builds an `rgba(r, g, b, a)` string from a `#rrggbb` colour. Falls + * back to the input when the hex format is unrecognised so the + * renderer still gets a valid CSS colour for the stroke pass. + */ function withAlpha(hex: string, alpha: number): string { const m = /^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i.exec(hex); if (!m) return hex; @@ -537,9 +522,12 @@ function mapSize( }); } -// The sprite stamps centred on the target coordinate, but `anchor` (a point -// in the shared VIEWPORT square, see lib/glyph-marker.ts) should land there -// instead. Converts the offset between the two into output pixels. +/** + * The sprite stamps centred on the target coordinate, but `anchor` (a + * point in the shared `VIEWPORT` square, see `lib/glyph-marker.ts`) + * should land there instead. Converts the offset between the two into + * output pixels. + */ function anchorOffset( anchor: GlyphMarker["anchor"], targetSize: number, @@ -551,8 +539,7 @@ function anchorOffset( }; } -// 8-byte signature + 4-byte chunk length + 4-byte "IHDR" type + 4-byte width -// + 4-byte height. +/** 8-byte signature + 4-byte chunk length + 4-byte `IHDR` type + 4-byte width + 4-byte height. */ const PNG_HEADER_BYTES = 24; /** @@ -565,10 +552,7 @@ async function readPngSize( file: Blob, ): Promise<{ width: number; height: number }> { const header = await file.slice(0, PNG_HEADER_BYTES).arrayBuffer(); - // Diagnostic for https://github.com/kui/7dtd-map/issues/202 (flaky short - // read of bundled PNGs in CI). Throw a descriptive error with the file - // metadata that was visible at the moment of the short read so the next - // CI flake captures what would otherwise be lost behind a bare RangeError. + // WHY: diagnostic for https://github.com/kui/7dtd-map/issues/202 (flaky short read of bundled PNGs in CI). Throw a descriptive error with the file metadata visible at the moment of the short read so the next CI flake captures what would otherwise be lost behind a bare RangeError. if (header.byteLength < PNG_HEADER_BYTES) { const headerHex = Array.from(new Uint8Array(header)) .map((b) => b.toString(16).padStart(2, "0")) diff --git a/src/worker/lib/prefab-filter.ts b/src/worker/lib/prefab-filter.ts index cc074cf9..8403615a 100644 --- a/src/worker/lib/prefab-filter.ts +++ b/src/worker/lib/prefab-filter.ts @@ -17,8 +17,11 @@ import * as events from "../../lib/events.ts"; import { escapeHtml, printError, sleep } from "../../lib/utils.ts"; import { latestAddedVersion } from "../../lib/prefab-added-versions.ts"; -// One `header` per run followed by `chunk`s, so the main thread never -// deserializes one huge result. Complete when received count == total. +/** + * Wire messages from the filter worker. One `header` per run followed + * by `chunk`s so the main thread never deserializes one huge result. + * A run is complete when the received count reaches `header.total`. + */ export type PrefabsFilterOutputMessage = | { type: "header"; status: string; total: number } | { type: "chunk"; prefabs: HighlightedPrefab[] }; @@ -105,8 +108,7 @@ export class PrefabFilter { status: this.#status, total: this.#filtered.length, }); - // Detached so a newer run can start (and cancel this one) before the - // stream finishes; throttledInvoker awaits the returned promise. + // WHY: detached so a newer run can start and cancel this one before the stream finishes. throttledInvoker only awaits the returned promise. void this.#streamChunks(inputVersion, this.#filtered); } @@ -116,8 +118,7 @@ export class PrefabFilter { ): Promise { try { for (let i = 0; i < prefabs.length; i += CHUNK_SIZE) { - // Must precede the post: guarantees a stale stream never delivers a - // chunk after newer input has arrived. + // INVARIANT: the staleness check must precede the post so a stale stream never delivers a chunk after newer input has arrived. if (inputVersion !== this.#inputVersion) return; await this.#listeners.dispatch({ type: "chunk", @@ -281,8 +282,7 @@ export class PrefabFilter { return prefabs.flatMap((prefab) => { const allMatchedBlocks = matchedPrefabNames[prefab.name]; if (!allMatchedBlocks) return []; - // Count and threshold use the full set so the reported totals stay true; - // only the transmitted list is capped for serialize/DOM cost. + // INVARIANT: count and threshold use the full set so the reported totals stay true. Only the transmitted list is capped for serialize and DOM cost. const matchedBlockCount = allMatchedBlocks.reduce( (acc, b) => acc + (b.count ?? 0), 0, @@ -333,9 +333,7 @@ export class PrefabFilter { const { markCoords } = this; const meshSizes = await this.#meshSizesHolder.get(); this.#filtered.forEach((p) => { - // decoration.position is the SW corner of the rotated AABB, so add the - // rotation-aware half-extents to compare against the flag from the - // prefab's centre instead of its corner. + // WHY: decoration.position is the SW corner of the rotated AABB, so add the rotation-aware half-extents to compare against the flag from the prefab's centre instead of its corner. const c = prefabCenter(p, meshSizes); p.distance = [ computeDirection(c, markCoords), @@ -434,8 +432,11 @@ function computeDirection( return "NW"; } -// Returns null instead of throwing when `source` is not a valid RegExp pattern, -// so partial / mid-typed user input does not break the worker pipeline. +/** + * Returns `null` instead of throwing when `source` is not a valid + * RegExp pattern. Partial or mid-typed user input must not break the + * worker pipeline. + */ function tryCompileRegex(source: string, flags: string): RegExp | null { try { return new RegExp(source, flags); @@ -444,15 +445,16 @@ function tryCompileRegex(source: string, flags: string): RegExp | null { } } -// Escapes non-matching segments and wraps matches in , so the resulting -// string is safe to assign to innerHTML even when `str` came from user XML. -// Exported for testing. +/** + * Escapes non-matching segments and wraps matches in ``, so the + * resulting string is safe to assign to `innerHTML` even when `str` + * came from user XML. Exported for testing. + */ export function matchAndHighlight(str: string, regex: RegExp) { let isMatched = false; let lastIndex = 0; let out = ""; - // Use matchAll so we can interleave escaped non-matches with wrapped matches - // regardless of whether the regex has the global flag set by the caller. + // WHY: matchAll lets us interleave escaped non-matches with wrapped matches whether or not the caller's regex has the global flag. const source = regex.global ? regex : new RegExp(regex.source, regex.flags + "g"); diff --git a/src/worker/map-renderer.ts b/src/worker/map-renderer.ts index 37444a3d..ced07d25 100644 --- a/src/worker/map-renderer.ts +++ b/src/worker/map-renderer.ts @@ -10,9 +10,7 @@ import type { let map: MapRenderer | null = null; -// The prefab sign and flag markers stamp SVG path data baked at build time -// (see tools/generate-glyph-markers.ts) instead of rendering glyphs from a -// webfont, so it's fetched once here rather than per MapRenderer instance. +// WHY: fetch the baked glyph path once at module load. Every MapRenderer instance stamps the same SVG path data from tools/generate-glyph-markers.ts and would otherwise re-fetch. const signMarkerReady: Promise = fetchJson( "../heavy-ballot-x-path.json", ); @@ -35,19 +33,16 @@ async function handleMessage(message: MapRendererInputMessage): Promise { throw Error("Unexpected state"); } } else if (message.canvas || message.compositeCanvas) { - // The OffscreenCanvases are captured by the first message and must not be - // replaced by later messages; drop any stray canvas fields defensively. + // INVARIANT: OffscreenCanvases captured by the first message must not be replaced by later messages. Drop any stray canvas fields defensively. delete message.canvas; delete message.compositeCanvas; } Object.assign(map, message); - // Not awaited: awaiting would serialize the queue below behind each - // throttled render instead of letting throttledInvoker coalesce them. + // WHY: not awaited. Awaiting would serialize the queue below behind each throttled render instead of letting throttledInvoker coalesce them. map.update().catch(printError); } -// Serialize handling so messages arriving while the MapRenderer construction -// awaits the glyph fetches are queued instead of dropped. +// WHY: serialize message handling so messages arriving while the MapRenderer construction awaits the glyph fetches are queued instead of dropped. let queue: Promise = Promise.resolve(); onmessage = (event: MessageEvent) => { queue = queue.then(() => handleMessage(event.data)).catch(printError); diff --git a/src/worker/prefabs-filter.ts b/src/worker/prefabs-filter.ts index 9fa462b3..1941f9c7 100644 --- a/src/worker/prefabs-filter.ts +++ b/src/worker/prefabs-filter.ts @@ -21,7 +21,7 @@ const prefabs = new PrefabFilter( onmessage = ({ data }: MessageEvent) => { console.log("Prefab-filter received message: ", data); Object.assign(prefabs, data); - // Bump before update() so an in-flight stream from the previous input aborts. + // WHY: bump before update() so an in-flight stream from the previous input aborts. prefabs.bumpInputVersion(); prefabs.update().catch(printError); }; diff --git a/tools/lint-plugins/require-comment-rationale.ts b/tools/lint-plugins/require-comment-rationale.ts index 639eb4cd..7b4afe14 100644 --- a/tools/lint-plugins/require-comment-rationale.ts +++ b/tools/lint-plugins/require-comment-rationale.ts @@ -44,10 +44,6 @@ const EXCLUDED_PATHS: readonly string[] = [ "/src/index/terrain-viewer/hover-controller.ts", "/src/index/terrain-viewer/marker-sprites.ts", "/src/index/terrain-viewer/prefab-boxes.ts", - "/src/worker/lib/map-renderer.ts", - "/src/worker/lib/prefab-filter.ts", - "/src/worker/map-renderer.ts", - "/src/worker/prefabs-filter.ts", "/e2e/index.spec.ts", "/e2e/prefabs.spec.ts", "/playwright.config.ts",