Files
msd-core/tests/helpers/shell-doc-scan.cjs
Jakub Zych a9a7a328e6 refactor: hard-fork GSD -> MSD (Make Software Done)
Mechanical rename produced by scripts/msd-rename.cjs: gsd/Gsd/GSD -> msd/Msd/MSD
across contents and paths, upstream package/repo coordinates -> @golem15/msd-core
and golem15com/msd-core. Deep links into upstream history, sibling upstream
packages, the GSD-2 import feature, CHANGELOG.md and .changeset/ are kept as-is.

Hand edits on top: MSD block-letter banner and logos, LICENSE copyright line,
package/plugin identity, regenerated lockfile, install-tree fixtures, derived
registries and benchmark baseline; migration checksum baseline re-locked
(MSD keeps its own install state, so no install had applied the old sums);
sort-order and regex-escaped expectations in tests adjusted.
2026-10-06 01:47:40 +02:00

37 lines
1.4 KiB
JavaScript

'use strict';
const { scanFencedBlocks } = require('../../msd-core/bin/lib/markdown-sectionizer.cjs');
const { splitLines } = require('../../msd-core/bin/lib/text-lines.cjs');
/**
* Fold unquoted shell backslash-newline continuations into logical lines.
*
* A newline is continued only when the immediately preceding backslash run is
* odd: the final backslash is consumed and every earlier pair stays literal.
* This deliberately remains a text heuristic, not a shell parser; in
* particular, a backslash-newline inside single quotes is a known blind spot.
*/
function foldShellContinuations(src) {
return src.replace(
/(^|[^\\])((?:\\\\)*)\\\n[ \t]*/gm,
(_match, prefix, literalPairs) => `${prefix}${literalPairs} `,
);
}
/** Return regex matches from logical lines inside closed bash/sh fences. */
function findShellFencedMatches(src, pattern) {
const lines = splitLines(src);
return scanFencedBlocks(lines).flatMap((block) => {
if (block.closeLineIdx === -1) return [];
const language = block.infoString.trim().toLowerCase();
if (language !== 'bash' && language !== 'sh') return [];
const body = lines.slice(block.openLineIdx + 1, block.closeLineIdx).join('\n');
return Array.from(
foldShellContinuations(body).matchAll(pattern),
(match) => match[0],
);
});
}
module.exports = { foldShellContinuations, findShellFencedMatches };