0.2.5-dev: a restore-defaults loadout sync is never overwritten by an older in-flight sync (PR #540 by @Xinglan233, ported); importing a loadout with ops is refused before writing when the DIY data is missing (PR #538 by @Xinglan233, ported); the player package's package.json keeps only scripts whose files ship (#531) and its docs link unshipped files to the release tag on GitHub (#530); golden: unchanged

This commit is contained in:
sganggs committed 2026-10-12 14:45:01 +08:00
1 parent 7fd0478dc0
commit 52b70434d0
13 files changed
+610 -5

No files matched your search

+26
View File
@@ -12,6 +12,7 @@ import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';
import { dirname, join, normalize } from 'node:path';
import { fileURLToPath } from 'node:url';
import { designText, DESIGN_DIRS } from './helpers/designDocs.js';
import { PLAYER_MARKDOWN, rewritePlayerDoc, selectTracked, trackedFiles } from '../tools/package.mjs';
const ROOT = join(dirname(fileURLToPath(import.meta.url)), '..');
/** Each document with the least number of paths it names (a guard against an extraction that finds nothing). */
@@ -141,3 +142,28 @@ test('DESIGN: every "DESIGN §N" cited in the repository (code comments, tests,
assert.ok(cited >= 700, `only ${cited} citations found — is the scan broken?`);
assert.deepEqual(bad, [], 'citations of a section or subsection with no heading');
});
test('shipped markdown: a source link exists or is releases/latest, and the packaged copy only links to shipped files', () => {
const shipped = new Set(selectTracked(trackedFiles(ROOT)).keep);
const version = JSON.parse(readFileSync(join(ROOT, 'package.json'), 'utf8')).version;
assert.ok(PLAYER_MARKDOWN.length >= 6, PLAYER_MARKDOWN.join(' '));
for (const rel of PLAYER_MARKDOWN) {
const md = readFileSync(join(ROOT, rel), 'utf8');
for (const m of md.matchAll(/\]\(([^)\s]+)\)/g)) {
const href = m[1];
if (/^(?:[a-z]+:|#)/i.test(href)) continue;
const raw = href.replace(/#.*$/, '');
const norm = normalize(join(dirname(rel), raw)).split('\\').join('/');
if (norm.startsWith('..')) assert.match(norm, /^(?:\.\.\/)+releases\/latest$/, `${rel} → ${href}`);
else assert.ok(existsSync(join(ROOT, norm)), `${rel} → ${href}`);
}
const next = rewritePlayerDoc(md, rel, shipped, version);
for (const m of next.matchAll(/\]\(([^)\s]+)\)/g)) {
const href = m[1];
if (/^(?:[a-z][a-z0-9+.-]*:|#)/i.test(href)) continue;
const raw = href.replace(/#.*$/, '');
const norm = normalize(join(dirname(rel), raw)).split('\\').join('/');
assert.ok(shipped.has(norm), `${rel} packaged link ${href} (${norm}) is not in the zip`);
}
}
});