refactor(scripts): share regexp literal escaping (#99778)

This commit is contained in:
Dallin Romney
2026-07-03 20:20:28 -07:00
committed by GitHub
parent 19035bdca1
commit e7b5946da0
11 changed files with 30 additions and 40 deletions

View File

@@ -1,5 +1,6 @@
// Barnacle owns deterministic GitHub triage and auto-response behavior.
import { escapeRegExp } from "../lib/regexp.mjs";
import {
NEEDS_PR_CONTEXT_LABEL,
PROOF_SUFFICIENT_LABEL,
@@ -294,7 +295,7 @@ function extractIssueFormValue(body, field) {
if (!body) {
return "";
}
const escapedField = field.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
const escapedField = escapeRegExp(field);
const regex = new RegExp(
`(?:^|\\n)###\\s+${escapedField}\\s*\\n([\\s\\S]*?)(?=\\n###\\s+|$)`,
"i",
@@ -317,7 +318,7 @@ function hasLinkedReference(text) {
}
function hasFilledTemplateLine(body, field) {
const escapedField = field.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
const escapedField = escapeRegExp(field);
const regex = new RegExp(`^\\s*-\\s*${escapedField}:\\s*\\S`, "im");
return regex.test(body);
}
@@ -334,7 +335,7 @@ function hasMostlyBlankTemplate(body) {
"Root cause",
"Target test or file",
].filter((field) => {
const escapedField = field.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
const escapedField = escapeRegExp(field);
const regex = new RegExp(`^\\s*-\\s*${escapedField}(?: \\([^)]*\\))?:\\s*$`, "im");
return regex.test(body);
}).length;

View File

@@ -1,5 +1,6 @@
// Shared PR context and evidence policy for GitHub checks and label decisions.
import { readBoundedResponseText } from "../lib/bounded-response.mjs";
import { escapeRegExp } from "../lib/regexp.mjs";
/** ClawSweeper-owned labels that OpenClaw preserves but does not mutate. */
export const PROOF_OVERRIDE_LABEL = "proof: override";
@@ -53,10 +54,6 @@ const legacyProofFieldNames = [
const missingValueRegex =
/^(?:n\/?a|none|not applicable|tbd|todo|unknown|unsure|none provided|no evidence|not tested|untested|did not test|didn't test|could not test|couldn't test|-|(?:-{3,}|\*{3,}|_{3,})|\[[^\]]*\])\.?$/i;
function escapeRegex(text) {
return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
function createTimeoutError(label, timeoutMs) {
const error = new Error(`${label} timed out after ${timeoutMs}ms`);
error.code = "ETIMEDOUT";
@@ -290,7 +287,7 @@ function extractMarkdownSections(headingRegex, body = "") {
}
export function hasAuthoredPullRequestSection(heading, body = "") {
const headingPattern = new RegExp(`^#{2,6}\\s+${escapeRegex(heading)}\\b[^\\n]*$`, "im");
const headingPattern = new RegExp(`^#{2,6}\\s+${escapeRegExp(heading)}\\b[^\\n]*$`, "im");
return !isMissingValue(extractMarkdownSections(headingPattern, body).at(-1) ?? "");
}
@@ -300,7 +297,7 @@ function extractLegacyProofSections(body = "") {
function fieldLineRegex(name) {
return new RegExp(
`^\\s*(?:[-*]\\s*)?(?:\\*\\*)?${escapeRegex(name)}(?:\\s*\\([^)]*\\))?(?:\\*\\*)?\\s*:\\s*(.*)$`,
`^\\s*(?:[-*]\\s*)?(?:\\*\\*)?${escapeRegExp(name)}(?:\\s*\\([^)]*\\))?(?:\\*\\*)?\\s*:\\s*(.*)$`,
"i",
);
}
@@ -375,7 +372,7 @@ function result(status, reason, details = {}) {
}
function extractMarkerField(marker, name) {
const match = marker.match(new RegExp(`\\b${escapeRegex(name)}=([^\\s>]+)`, "i"));
const match = marker.match(new RegExp(`\\b${escapeRegExp(name)}=([^\\s>]+)`, "i"));
return match?.[1] ?? "";
}