Compile a minimal glob into a NON-backtracking matcher anchored against
vault-relative paths (forward-slash separated). Supports:
* — any run of non-slash characters
** — any run of characters including slashes (globstar)
? — exactly one non-slash character
No bracket sets, no ! negation, no {a,b} alternation. Patterns are matched
against the full vault-relative path (e.g. 02_Personal/Inbox/x.md). The
returned object exposes .test(path) so call sites read like the old
globToRegex(...).test(...).
v3.10.0-rc.71 (post-rc.66 re-sweep, ReDoS class — closes the rc.68 sibling): matching
is now a NON-backtracking DP (matchWildcardTokens), NOT a RegExp. The
pre-rc.71 globToRegex compiled *→[^/]* / **→.* and (rc.68) collapsed only
ADJACENT unbounded quantifiers. A glob with wildcards SEPARATED BY LITERALS
(*a*a*… → ^[^/]*a[^/]*a…$, or **a**a…) was still catastrophic — the rc.68
adjacency-collapse cannot touch a literal-separated run, and its structural guard
(asserting "no adjacent quantifiers") gave false confidence against this shape. The
catastrophe scales with the matched PATH length (paths can be 100+ chars deep), so a
wildcard count cap is not structurally safe. This filter runs via .test() on EVERY
path of EVERY vault scan, so one fat-fingered --exclude-glob / --read-paths froze
every scan; the linear matcher removes the backtracking engine entirely.
Compile a minimal glob into a NON-backtracking matcher anchored against vault-relative paths (forward-slash separated). Supports:
*— any run of non-slash characters**— any run of characters including slashes (globstar)?— exactly one non-slash character No bracket sets, no!negation, no{a,b}alternation. Patterns are matched against the full vault-relative path (e.g.02_Personal/Inbox/x.md). The returned object exposes.test(path)so call sites read like the oldglobToRegex(...).test(...).v3.10.0-rc.71 (post-rc.66 re-sweep, ReDoS class — closes the rc.68 sibling): matching is now a NON-backtracking DP (
matchWildcardTokens), NOT aRegExp. The pre-rc.71globToRegexcompiled*→[^/]*/**→.*and (rc.68) collapsed only ADJACENT unbounded quantifiers. A glob with wildcards SEPARATED BY LITERALS (*a*a*…→^[^/]*a[^/]*a…$, or**a**a…) was still catastrophic — the rc.68 adjacency-collapse cannot touch a literal-separated run, and its structural guard (asserting "no adjacent quantifiers") gave false confidence against this shape. The catastrophe scales with the matched PATH length (paths can be 100+ chars deep), so a wildcard count cap is not structurally safe. This filter runs via.test()on EVERY path of EVERY vault scan, so one fat-fingered--exclude-glob/--read-pathsfroze every scan; the linear matcher removes the backtracking engine entirely.