diff --git a/package.json b/package.json index 66cf901..fc2fb33 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ "eslint-plugin-tsdoc": "0.4.0", "execa": "9.6.0", "globals": "16.5.0", - "human-regex": "2.1.5", + "human-regex": "2.2.0", "prettier": "3.6.2", "rimraf": "6.1.0", "tsup": "8.5.0", diff --git a/patches/human-regex@2.1.5.patch b/patches/human-regex@2.1.5.patch deleted file mode 100644 index cb2f62e..0000000 --- a/patches/human-regex@2.1.5.patch +++ /dev/null @@ -1,117 +0,0 @@ -diff --git a/README.md b/README.md -index f95a4dc41c1f3a8371d694e1e1913f275acb22fa..afb60390589d9bf60b0f7297f24c29ca348a1866 100644 ---- a/README.md -+++ b/README.md -@@ -93,8 +93,13 @@ Creates a new regex builder instance. - | `.anyCharacter()` | Adds a pattern for any character (`.`). | `.` | - | `.literal("text")` | Adds a literal text pattern. | `["text"]` | - | `.or()` | Adds an OR pattern. | `\|` | -+| `.newline()` | Adds a pattern for newline characters. | `(\r\n\|\r\|\n)` | - | `.range("digit")` | Adds a range pattern for digits (`0-9`). | `[0-9]` | --| `.notRange("aeiou")` | Excludes characters from the pattern. | `[^aeiou]` | -+| `.notRange("letter")` | Adds a range pattern for non-letters | `[^a-zA-Z]` | -+| `.anyOf("aeiou\\s")` | Adds list of accepted characters | `[aeiou\s]` | -+| `.notAnyOf("aeiou\\s")` | Adds list of excluded characters | `[^aeiou\s]` | -+ -+ - - ### Quantifiers - -@@ -165,6 +170,26 @@ Creates a new regex builder instance. - - `Patterns.url`: Predefined URL pattern. - - `Patterns.phoneInternational`: Predefined international phone number pattern. - -+### Predefined Ranges -+ -+For use with `range()` and `notRange()`: -+ -+ digit: "0-9", -+ lowercaseLetter: "a-z", -+ uppercaseLetter: "A-Z", -+ letter: "a-zA-Z", -+ alphanumeric: "a-zA-Z0-9", -+ anyCharacter: ".", -+ -+| RangeKey | Range value | -+| ------------------------ | --------------- | -+| `digit` | `0-9` | -+| `lowercaseLetter` | `a-z` | -+| `uppercaseLetter` | `A-Z` | -+| `letter` | `a-zA-Z` | -+| `alphanumeric` | `a-zA-Z0-9` | -+| `anyCharacter` | `.` | -+ - ## Examples - - ### Combining with Existing Regex -diff --git a/dist/human-regex.cjs.js b/dist/human-regex.cjs.js -index 97b4577ef5d72b9edf8e201312f806a5d900ac1b..505e4f2771a4145ff427540ef0d79c2833551d36 100644 ---- a/dist/human-regex.cjs.js -+++ b/dist/human-regex.cjs.js -@@ -1,2 +1,2 @@ --"use strict";const t=new Map,r={GLOBAL:"g",NON_SENSITIVE:"i",MULTILINE:"m",DOT_ALL:"s",UNICODE:"u",STICKY:"y"},e=Object.freeze({digit:"0-9",lowercaseLetter:"a-z",uppercaseLetter:"A-Z",letter:"a-zA-Z",alphanumeric:"a-zA-Z0-9",anyCharacter:"."}),a=Object.freeze({zeroOrMore:"*",oneOrMore:"+",optional:"?"});class n{constructor(){this.parts=[],this.flags=new Set}digit(){return this.add("\\d")}special(){return this.add("(?=.*[!@#$%^&*])")}word(){return this.add("\\w")}whitespace(){return this.add("\\s")}nonWhitespace(){return this.add("\\S")}literal(r){return this.add(function(r){t.has(r)||t.set(r,r.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"));return t.get(r)}(r))}or(){return this.add("|")}range(t){const r=e[t];if(!r)throw new Error(`Unknown range: ${t}`);return this.add(`[${r}]`)}notRange(t){return this.add(`[^${t}]`)}lazy(){const t=this.parts.pop();if(!t)throw new Error("No quantifier to make lazy");return this.add(`${t}?`)}letter(){return this.add("[a-zA-Z]")}anyCharacter(){return this.add(".")}negativeLookahead(t){return this.add(`(?!${t})`)}positiveLookahead(t){return this.add(`(?=${t})`)}positiveLookbehind(t){return this.add(`(?<=${t})`)}negativeLookbehind(t){return this.add(`(?`)}startGroup(){return this.add("(?:")}startCaptureGroup(){return this.add("(")}wordBoundary(){return this.add("\\b")}nonWordBoundary(){return this.add("\\B")}endGroup(){return this.add(")")}startAnchor(){return this.add("^")}endAnchor(){return this.add("$")}global(){return this.flags.add(r.GLOBAL),this}nonSensitive(){return this.flags.add(r.NON_SENSITIVE),this}multiline(){return this.flags.add(r.MULTILINE),this}dotAll(){return this.flags.add(r.DOT_ALL),this}sticky(){return this.flags.add(r.STICKY),this}unicodeChar(t){this.flags.add(r.UNICODE);const e=new Set(["u","l","t","m","o"]);if(void 0!==t&&!e.has(t))throw new Error(`Invalid Unicode letter variant: ${t}`);return this.add(`\\p{L${null!=t?t:""}}`)}unicodeDigit(){return this.flags.add(r.UNICODE),this.add("\\p{N}")}unicodePunctuation(){return this.flags.add(r.UNICODE),this.add("\\p{P}")}unicodeSymbol(){return this.flags.add(r.UNICODE),this.add("\\p{S}")}repeat(t){if(0===this.parts.length)throw new Error("No pattern to repeat");const r=this.parts.pop();return this.parts.push(`(${r}){${t}}`),this}ipv4Octet(){return this.add("(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)")}protocol(){return this.add("https?://")}www(){return this.add("(www\\.)?")}tld(){return this.add("(com|org|net)")}path(){return this.add("(/\\w+)*")}add(t){return this.parts.push(t),this}toString(){return this.parts.join("")}toRegExp(){return new RegExp(this.toString(),[...this.flags].join(""))}}const d=()=>new n,s=(()=>{const t=t=>{const r=t().toRegExp();return()=>new RegExp(r.source,r.flags)};return{email:t((()=>d().startAnchor().word().oneOrMore().literal("@").word().oneOrMore().startGroup().literal(".").word().oneOrMore().endGroup().zeroOrMore().literal(".").letter().atLeast(2).endAnchor())),url:t((()=>d().startAnchor().protocol().www().word().oneOrMore().literal(".").tld().path().endAnchor())),phoneInternational:t((()=>d().startAnchor().literal("+").digit().between(1,3).literal("-").digit().between(3,14).endAnchor()))}})();exports.Flags=r,exports.Patterns=s,exports.Quantifiers=a,exports.Ranges=e,exports.createRegex=d; -+"use strict";const t=new Map,r={GLOBAL:"g",NON_SENSITIVE:"i",MULTILINE:"m",DOT_ALL:"s",UNICODE:"u",STICKY:"y"},e=Object.freeze({digit:"0-9",lowercaseLetter:"a-z",uppercaseLetter:"A-Z",letter:"a-zA-Z",alphanumeric:"a-zA-Z0-9",anyCharacter:"."}),n=Object.freeze({zeroOrMore:"*",oneOrMore:"+",optional:"?"});class a{constructor(){this.parts=[],this.flags=new Set}digit(){return this.add("\\d")}special(){return this.add("(?=.*[!@#$%^&*])")}word(){return this.add("\\w")}whitespace(){return this.add("\\s")}nonWhitespace(){return this.add("\\S")}literal(r){return this.add(function(r){t.has(r)||t.set(r,r.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"));return t.get(r)}(r))}or(){return this.add("|")}range(t){const r=e[t];if(!r)throw new Error(`Unknown range: ${t}`);return this.add(`[${r}]`)}notRange(t){const r=e[t];if(!r)throw new Error(`Unknown range: ${t}`);return this.add(`[^${r}]`)}anyOf(t){return this.add(`[${t}]`)}notAnyOf(t){return this.add(`[^${t}]`)}lazy(){const t=this.parts.pop();if(!t)throw new Error("No quantifier to make lazy");return this.add(`${t}?`)}letter(){return this.add("[a-zA-Z]")}anyCharacter(){return this.add(".")}newline(){return this.add("(?:\\r\\n|\\r|\\n)")}negativeLookahead(t){return this.add(`(?!${t})`)}positiveLookahead(t){return this.add(`(?=${t})`)}positiveLookbehind(t){return this.add(`(?<=${t})`)}negativeLookbehind(t){return this.add(`(?`)}startGroup(){return this.add("(?:")}startCaptureGroup(){return this.add("(")}wordBoundary(){return this.add("\\b")}nonWordBoundary(){return this.add("\\B")}endGroup(){return this.add(")")}startAnchor(){return this.add("^")}endAnchor(){return this.add("$")}global(){return this.flags.add(r.GLOBAL),this}nonSensitive(){return this.flags.add(r.NON_SENSITIVE),this}multiline(){return this.flags.add(r.MULTILINE),this}dotAll(){return this.flags.add(r.DOT_ALL),this}sticky(){return this.flags.add(r.STICKY),this}unicodeChar(t){this.flags.add(r.UNICODE);const e=new Set(["u","l","t","m","o"]);if(void 0!==t&&!e.has(t))throw new Error(`Invalid Unicode letter variant: ${t}`);return this.add(`\\p{L${null!=t?t:""}}`)}unicodeDigit(){return this.flags.add(r.UNICODE),this.add("\\p{N}")}unicodePunctuation(){return this.flags.add(r.UNICODE),this.add("\\p{P}")}unicodeSymbol(){return this.flags.add(r.UNICODE),this.add("\\p{S}")}repeat(t){if(0===this.parts.length)throw new Error("No pattern to repeat");const r=this.parts.pop();return this.parts.push(`(${r}){${t}}`),this}ipv4Octet(){return this.add("(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)")}protocol(){return this.add("https?://")}www(){return this.add("(www\\.)?")}tld(){return this.add("(com|org|net)")}path(){return this.add("(/\\w+)*")}add(t){return this.parts.push(t),this}toString(){return this.parts.join("")}toRegExp(){return new RegExp(this.toString(),[...this.flags].join(""))}}const d=()=>new a,s=(()=>{const t=t=>{const r=t().toRegExp();return()=>new RegExp(r.source,r.flags)};return{email:t((()=>d().startAnchor().word().oneOrMore().literal("@").word().oneOrMore().startGroup().literal(".").word().oneOrMore().endGroup().zeroOrMore().literal(".").letter().atLeast(2).endAnchor())),url:t((()=>d().startAnchor().protocol().www().word().oneOrMore().literal(".").tld().path().endAnchor())),phoneInternational:t((()=>d().startAnchor().literal("+").digit().between(1,3).literal("-").digit().between(3,14).endAnchor()))}})();exports.Flags=r,exports.Patterns=s,exports.Quantifiers=n,exports.Ranges=e,exports.createRegex=d; - //# sourceMappingURL=human-regex.cjs.js.map -diff --git a/dist/human-regex.cjs.js.map b/dist/human-regex.cjs.js.map -index 4e1d7236724f234a49246eac7b74b185b3709517..8cd9133392d204bae0ace0b8e10b1b01e303572d 100644 ---- a/dist/human-regex.cjs.js.map -+++ b/dist/human-regex.cjs.js.map -@@ -1 +1 @@ --{"version":3,"file":"human-regex.cjs.js","sources":["../src/human-regex.ts"],"sourcesContent":["type PartialBut = Partial & Pick;\n\nconst escapeCache = new Map();\n\nconst Flags = {\n GLOBAL: \"g\",\n NON_SENSITIVE: \"i\",\n MULTILINE: \"m\",\n DOT_ALL: \"s\",\n UNICODE: \"u\",\n STICKY: \"y\",\n} as const;\n\nconst Ranges = Object.freeze({\n digit: \"0-9\",\n lowercaseLetter: \"a-z\",\n uppercaseLetter: \"A-Z\",\n letter: \"a-zA-Z\",\n alphanumeric: \"a-zA-Z0-9\",\n anyCharacter: \".\",\n});\n\ntype RangeKeys = keyof typeof Ranges;\n\nconst Quantifiers = Object.freeze({\n zeroOrMore: \"*\",\n oneOrMore: \"+\",\n optional: \"?\",\n});\n\ntype Quantifiers =\n | \"exactly\"\n | \"atLeast\"\n | \"atMost\"\n | \"between\"\n | \"oneOrMore\"\n | \"zeroOrMore\"\n | \"repeat\";\ntype QuantifierMethods = Quantifiers | \"optional\" | \"lazy\";\n\ntype WithLazy = HumanRegex;\ntype Base = Omit;\ntype AtStart = Omit;\ntype AfterAnchor = Omit;\ntype SimpleQuantifier = Omit;\ntype LazyQuantifier = Omit;\n\nclass HumanRegex {\n private parts: string[];\n private flags: Set;\n\n constructor() {\n this.parts = [];\n this.flags = new Set();\n }\n\n digit(): Base {\n return this.add(\"\\\\d\");\n }\n\n special(): Base {\n return this.add(\"(?=.*[!@#$%^&*])\");\n }\n\n word(): Base {\n return this.add(\"\\\\w\");\n }\n\n whitespace(): Base {\n return this.add(\"\\\\s\");\n }\n\n nonWhitespace(): Base {\n return this.add(\"\\\\S\");\n }\n\n literal(text: string): this {\n return this.add(escapeLiteral(text));\n }\n\n or(): AfterAnchor {\n return this.add(\"|\");\n }\n\n range(name: RangeKeys): Base {\n const range = Ranges[name];\n if (!range) throw new Error(`Unknown range: ${name}`);\n return this.add(`[${range}]`);\n }\n\n notRange(chars: string): Base {\n return this.add(`[^${chars}]`);\n }\n\n lazy(): Base {\n const lastPart = this.parts.pop();\n if (!lastPart) throw new Error(\"No quantifier to make lazy\");\n return this.add(`${lastPart}?`);\n }\n\n letter(): Base {\n return this.add(\"[a-zA-Z]\");\n }\n\n anyCharacter(): Base {\n return this.add(\".\");\n }\n\n negativeLookahead(pattern: string): Base {\n return this.add(`(?!${pattern})`);\n }\n\n positiveLookahead(pattern: string): Base {\n return this.add(`(?=${pattern})`);\n }\n\n positiveLookbehind(pattern: string): Base {\n return this.add(`(?<=${pattern})`);\n }\n\n negativeLookbehind(pattern: string): Base {\n return this.add(`(?`);\n }\n\n startGroup(): AfterAnchor {\n return this.add(\"(?:\");\n }\n\n startCaptureGroup(): AfterAnchor {\n return this.add(\"(\");\n }\n\n wordBoundary(): Base {\n return this.add(\"\\\\b\");\n }\n\n nonWordBoundary(): Base {\n return this.add(\"\\\\B\");\n }\n\n endGroup(): Base {\n return this.add(\")\");\n }\n\n startAnchor(): AfterAnchor {\n return this.add(\"^\");\n }\n\n endAnchor(): AfterAnchor {\n return this.add(\"$\");\n }\n\n global(): this {\n this.flags.add(Flags.GLOBAL);\n return this;\n }\n\n nonSensitive(): this {\n this.flags.add(Flags.NON_SENSITIVE);\n return this;\n }\n\n multiline(): this {\n this.flags.add(Flags.MULTILINE);\n return this;\n }\n\n dotAll(): this {\n this.flags.add(Flags.DOT_ALL);\n return this;\n }\n\n sticky(): this {\n this.flags.add(Flags.STICKY);\n return this;\n }\n\n unicodeChar(variant?: \"u\" | \"l\" | \"t\" | \"m\" | \"o\"): Base {\n this.flags.add(Flags.UNICODE);\n const validVariants = new Set([\"u\", \"l\", \"t\", \"m\", \"o\"] as const);\n\n if (variant !== undefined && !validVariants.has(variant)) {\n throw new Error(`Invalid Unicode letter variant: ${variant}`);\n }\n\n return this.add(`\\\\p{L${variant ?? \"\"}}`);\n }\n\n unicodeDigit(): Base {\n this.flags.add(Flags.UNICODE);\n return this.add(\"\\\\p{N}\");\n }\n\n unicodePunctuation(): Base {\n this.flags.add(Flags.UNICODE);\n return this.add(\"\\\\p{P}\");\n }\n\n unicodeSymbol(): Base {\n this.flags.add(Flags.UNICODE);\n return this.add(\"\\\\p{S}\");\n }\n\n repeat(count: number): Base {\n if (this.parts.length === 0) {\n throw new Error(\"No pattern to repeat\");\n }\n\n const lastPart = this.parts.pop();\n this.parts.push(`(${lastPart}){${count}}`);\n return this;\n }\n\n ipv4Octet(): Base {\n return this.add(\"(25[0-5]|2[0-4]\\\\d|1\\\\d\\\\d|[1-9]\\\\d|\\\\d)\");\n }\n\n protocol(): Base {\n return this.add(\"https?://\");\n }\n\n www(): Base {\n return this.add(\"(www\\\\.)?\");\n }\n\n tld(): Base {\n return this.add(\"(com|org|net)\");\n }\n\n path(): Base {\n return this.add(\"(/\\\\w+)*\");\n }\n\n private add(part: string): this {\n this.parts.push(part);\n return this;\n }\n\n toString(): string {\n return this.parts.join(\"\");\n }\n\n toRegExp(): RegExp {\n return new RegExp(this.toString(), [...this.flags].join(\"\"));\n }\n}\n\nfunction escapeLiteral(text: string): string {\n if (!escapeCache.has(text)) {\n escapeCache.set(text, text.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\"));\n }\n return escapeCache.get(text)!;\n}\n\nconst createRegex = (): AtStart => new HumanRegex();\n\nconst Patterns = (() => {\n const createCachedPattern = (\n builder: () => PartialBut\n ) => {\n const regex = builder().toRegExp();\n return () => new RegExp(regex.source, regex.flags);\n };\n\n return {\n email: createCachedPattern(() =>\n createRegex()\n .startAnchor()\n .word()\n .oneOrMore()\n .literal(\"@\")\n .word()\n .oneOrMore()\n .startGroup()\n .literal(\".\")\n .word()\n .oneOrMore()\n .endGroup()\n .zeroOrMore()\n .literal(\".\")\n .letter()\n .atLeast(2)\n .endAnchor()\n ),\n url: createCachedPattern(() =>\n createRegex()\n .startAnchor()\n .protocol()\n .www()\n .word()\n .oneOrMore()\n .literal(\".\")\n .tld()\n .path()\n .endAnchor()\n ),\n phoneInternational: createCachedPattern(() =>\n createRegex()\n .startAnchor()\n .literal(\"+\")\n .digit()\n .between(1, 3)\n .literal(\"-\")\n .digit()\n .between(3, 14)\n .endAnchor()\n ),\n };\n})();\n\nexport { createRegex, Patterns, Flags, Ranges, Quantifiers };\n"],"names":["escapeCache","Map","Flags","GLOBAL","NON_SENSITIVE","MULTILINE","DOT_ALL","UNICODE","STICKY","Ranges","Object","freeze","digit","lowercaseLetter","uppercaseLetter","letter","alphanumeric","anyCharacter","Quantifiers","zeroOrMore","oneOrMore","optional","HumanRegex","constructor","this","parts","flags","Set","add","special","word","whitespace","nonWhitespace","literal","text","has","set","replace","get","escapeLiteral","or","range","name","Error","notRange","chars","lazy","lastPart","pop","negativeLookahead","pattern","positiveLookahead","positiveLookbehind","negativeLookbehind","hasSpecialCharacter","hasDigit","hasLetter","exactly","n","atLeast","atMost","between","min","max","startNamedGroup","startGroup","startCaptureGroup","wordBoundary","nonWordBoundary","endGroup","startAnchor","endAnchor","global","nonSensitive","multiline","dotAll","sticky","unicodeChar","variant","validVariants","undefined","unicodeDigit","unicodePunctuation","unicodeSymbol","repeat","count","length","push","ipv4Octet","protocol","www","tld","path","part","toString","join","toRegExp","RegExp","createRegex","Patterns","createCachedPattern","builder","regex","source","email","url","phoneInternational"],"mappings":"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"} -\ No newline at end of file -+{"version":3,"file":"human-regex.cjs.js","sources":["../src/human-regex.ts"],"sourcesContent":["type PartialBut = Partial & Pick;\n\nconst escapeCache = new Map();\n\nconst Flags = {\n GLOBAL: \"g\",\n NON_SENSITIVE: \"i\",\n MULTILINE: \"m\",\n DOT_ALL: \"s\",\n UNICODE: \"u\",\n STICKY: \"y\",\n} as const;\n\nconst Ranges = Object.freeze({\n digit: \"0-9\",\n lowercaseLetter: \"a-z\",\n uppercaseLetter: \"A-Z\",\n letter: \"a-zA-Z\",\n alphanumeric: \"a-zA-Z0-9\",\n anyCharacter: \".\",\n});\n\ntype RangeKeys = keyof typeof Ranges;\n\nconst Quantifiers = Object.freeze({\n zeroOrMore: \"*\",\n oneOrMore: \"+\",\n optional: \"?\",\n});\n\ntype Quantifiers =\n | \"exactly\"\n | \"atLeast\"\n | \"atMost\"\n | \"between\"\n | \"oneOrMore\"\n | \"zeroOrMore\"\n | \"repeat\";\ntype QuantifierMethods = Quantifiers | \"optional\" | \"lazy\";\n\ntype WithLazy = HumanRegex;\ntype Base = Omit;\ntype AtStart = Omit;\ntype AfterAnchor = Omit;\ntype SimpleQuantifier = Omit;\ntype LazyQuantifier = Omit;\n\nclass HumanRegex {\n private parts: string[];\n private flags: Set;\n\n constructor() {\n this.parts = [];\n this.flags = new Set();\n }\n\n digit(): Base {\n return this.add(\"\\\\d\");\n }\n\n special(): Base {\n return this.add(\"(?=.*[!@#$%^&*])\");\n }\n\n word(): Base {\n return this.add(\"\\\\w\");\n }\n\n whitespace(): Base {\n return this.add(\"\\\\s\");\n }\n\n nonWhitespace(): Base {\n return this.add(\"\\\\S\");\n }\n\n literal(text: string): this {\n return this.add(escapeLiteral(text));\n }\n\n or(): AfterAnchor {\n return this.add(\"|\");\n }\n\n range(name: RangeKeys): Base {\n const range = Ranges[name];\n if (!range) throw new Error(`Unknown range: ${name}`);\n return this.add(`[${range}]`);\n }\n\n notRange(name: RangeKeys): Base {\n const range = Ranges[name];\n if (!range) throw new Error(`Unknown range: ${name}`);\n return this.add(`[^${range}]`);\n }\n\n anyOf(chars: string): Base {\n return this.add(`[${chars}]`);\n }\n\n notAnyOf(chars: string): Base {\n return this.add(`[^${chars}]`);\n }\n\n lazy(): Base {\n const lastPart = this.parts.pop();\n if (!lastPart) throw new Error(\"No quantifier to make lazy\");\n return this.add(`${lastPart}?`);\n }\n\n letter(): Base {\n return this.add(\"[a-zA-Z]\");\n }\n\n anyCharacter(): Base {\n return this.add(\".\");\n }\n\n newline(): Base {\n return this.add(\"(?:\\\\r\\\\n|\\\\r|\\\\n)\"); // Windows: \\r\\n, Unix: \\n, Old Macs: \\r\n }\n\n negativeLookahead(pattern: string): Base {\n return this.add(`(?!${pattern})`);\n }\n\n positiveLookahead(pattern: string): Base {\n return this.add(`(?=${pattern})`);\n }\n\n positiveLookbehind(pattern: string): Base {\n return this.add(`(?<=${pattern})`);\n }\n\n negativeLookbehind(pattern: string): Base {\n return this.add(`(?`);\n }\n\n startGroup(): AfterAnchor {\n return this.add(\"(?:\");\n }\n\n startCaptureGroup(): AfterAnchor {\n return this.add(\"(\");\n }\n\n wordBoundary(): Base {\n return this.add(\"\\\\b\");\n }\n\n nonWordBoundary(): Base {\n return this.add(\"\\\\B\");\n }\n\n endGroup(): Base {\n return this.add(\")\");\n }\n\n startAnchor(): AfterAnchor {\n return this.add(\"^\");\n }\n\n endAnchor(): AfterAnchor {\n return this.add(\"$\");\n }\n\n global(): this {\n this.flags.add(Flags.GLOBAL);\n return this;\n }\n\n nonSensitive(): this {\n this.flags.add(Flags.NON_SENSITIVE);\n return this;\n }\n\n multiline(): this {\n this.flags.add(Flags.MULTILINE);\n return this;\n }\n\n dotAll(): this {\n this.flags.add(Flags.DOT_ALL);\n return this;\n }\n\n sticky(): this {\n this.flags.add(Flags.STICKY);\n return this;\n }\n\n unicodeChar(variant?: \"u\" | \"l\" | \"t\" | \"m\" | \"o\"): Base {\n this.flags.add(Flags.UNICODE);\n const validVariants = new Set([\"u\", \"l\", \"t\", \"m\", \"o\"] as const);\n\n if (variant !== undefined && !validVariants.has(variant)) {\n throw new Error(`Invalid Unicode letter variant: ${variant}`);\n }\n\n return this.add(`\\\\p{L${variant ?? \"\"}}`);\n }\n\n unicodeDigit(): Base {\n this.flags.add(Flags.UNICODE);\n return this.add(\"\\\\p{N}\");\n }\n\n unicodePunctuation(): Base {\n this.flags.add(Flags.UNICODE);\n return this.add(\"\\\\p{P}\");\n }\n\n unicodeSymbol(): Base {\n this.flags.add(Flags.UNICODE);\n return this.add(\"\\\\p{S}\");\n }\n\n repeat(count: number): Base {\n if (this.parts.length === 0) {\n throw new Error(\"No pattern to repeat\");\n }\n\n const lastPart = this.parts.pop();\n this.parts.push(`(${lastPart}){${count}}`);\n return this;\n }\n\n ipv4Octet(): Base {\n return this.add(\"(25[0-5]|2[0-4]\\\\d|1\\\\d\\\\d|[1-9]\\\\d|\\\\d)\");\n }\n\n protocol(): Base {\n return this.add(\"https?://\");\n }\n\n www(): Base {\n return this.add(\"(www\\\\.)?\");\n }\n\n tld(): Base {\n return this.add(\"(com|org|net)\");\n }\n\n path(): Base {\n return this.add(\"(/\\\\w+)*\");\n }\n\n private add(part: string): this {\n this.parts.push(part);\n return this;\n }\n\n toString(): string {\n return this.parts.join(\"\");\n }\n\n toRegExp(): RegExp {\n return new RegExp(this.toString(), [...this.flags].join(\"\"));\n }\n}\n\nfunction escapeLiteral(text: string): string {\n if (!escapeCache.has(text)) {\n escapeCache.set(text, text.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\"));\n }\n return escapeCache.get(text)!;\n}\n\nconst createRegex = (): AtStart => new HumanRegex();\n\nconst Patterns = (() => {\n const createCachedPattern = (\n builder: () => PartialBut\n ) => {\n const regex = builder().toRegExp();\n return () => new RegExp(regex.source, regex.flags);\n };\n\n return {\n email: createCachedPattern(() =>\n createRegex()\n .startAnchor()\n .word()\n .oneOrMore()\n .literal(\"@\")\n .word()\n .oneOrMore()\n .startGroup()\n .literal(\".\")\n .word()\n .oneOrMore()\n .endGroup()\n .zeroOrMore()\n .literal(\".\")\n .letter()\n .atLeast(2)\n .endAnchor()\n ),\n url: createCachedPattern(() =>\n createRegex()\n .startAnchor()\n .protocol()\n .www()\n .word()\n .oneOrMore()\n .literal(\".\")\n .tld()\n .path()\n .endAnchor()\n ),\n phoneInternational: createCachedPattern(() =>\n createRegex()\n .startAnchor()\n .literal(\"+\")\n .digit()\n .between(1, 3)\n .literal(\"-\")\n .digit()\n .between(3, 14)\n .endAnchor()\n ),\n };\n})();\n\nexport { createRegex, Patterns, Flags, Ranges, Quantifiers };\n"],"names":["escapeCache","Map","Flags","GLOBAL","NON_SENSITIVE","MULTILINE","DOT_ALL","UNICODE","STICKY","Ranges","Object","freeze","digit","lowercaseLetter","uppercaseLetter","letter","alphanumeric","anyCharacter","Quantifiers","zeroOrMore","oneOrMore","optional","HumanRegex","constructor","this","parts","flags","Set","add","special","word","whitespace","nonWhitespace","literal","text","has","set","replace","get","escapeLiteral","or","range","name","Error","notRange","anyOf","chars","notAnyOf","lazy","lastPart","pop","newline","negativeLookahead","pattern","positiveLookahead","positiveLookbehind","negativeLookbehind","hasSpecialCharacter","hasDigit","hasLetter","exactly","n","atLeast","atMost","between","min","max","startNamedGroup","startGroup","startCaptureGroup","wordBoundary","nonWordBoundary","endGroup","startAnchor","endAnchor","global","nonSensitive","multiline","dotAll","sticky","unicodeChar","variant","validVariants","undefined","unicodeDigit","unicodePunctuation","unicodeSymbol","repeat","count","length","push","ipv4Octet","protocol","www","tld","path","part","toString","join","toRegExp","RegExp","createRegex","Patterns","createCachedPattern","builder","regex","source","email","url","phoneInternational"],"mappings":"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"} -\ No newline at end of file -diff --git a/dist/human-regex.esm.js b/dist/human-regex.esm.js -index dc4b9d6be5451cfb91113a83c449885ab684e3ba..be13291963f0f46f2625e84b7b63a83ef242ba4d 100644 ---- a/dist/human-regex.esm.js -+++ b/dist/human-regex.esm.js -@@ -1,2 +1,2 @@ --const t=new Map,r={GLOBAL:"g",NON_SENSITIVE:"i",MULTILINE:"m",DOT_ALL:"s",UNICODE:"u",STICKY:"y"},e=Object.freeze({digit:"0-9",lowercaseLetter:"a-z",uppercaseLetter:"A-Z",letter:"a-zA-Z",alphanumeric:"a-zA-Z0-9",anyCharacter:"."}),a=Object.freeze({zeroOrMore:"*",oneOrMore:"+",optional:"?"});class n{constructor(){this.parts=[],this.flags=new Set}digit(){return this.add("\\d")}special(){return this.add("(?=.*[!@#$%^&*])")}word(){return this.add("\\w")}whitespace(){return this.add("\\s")}nonWhitespace(){return this.add("\\S")}literal(r){return this.add(function(r){t.has(r)||t.set(r,r.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"));return t.get(r)}(r))}or(){return this.add("|")}range(t){const r=e[t];if(!r)throw new Error(`Unknown range: ${t}`);return this.add(`[${r}]`)}notRange(t){return this.add(`[^${t}]`)}lazy(){const t=this.parts.pop();if(!t)throw new Error("No quantifier to make lazy");return this.add(`${t}?`)}letter(){return this.add("[a-zA-Z]")}anyCharacter(){return this.add(".")}negativeLookahead(t){return this.add(`(?!${t})`)}positiveLookahead(t){return this.add(`(?=${t})`)}positiveLookbehind(t){return this.add(`(?<=${t})`)}negativeLookbehind(t){return this.add(`(?`)}startGroup(){return this.add("(?:")}startCaptureGroup(){return this.add("(")}wordBoundary(){return this.add("\\b")}nonWordBoundary(){return this.add("\\B")}endGroup(){return this.add(")")}startAnchor(){return this.add("^")}endAnchor(){return this.add("$")}global(){return this.flags.add(r.GLOBAL),this}nonSensitive(){return this.flags.add(r.NON_SENSITIVE),this}multiline(){return this.flags.add(r.MULTILINE),this}dotAll(){return this.flags.add(r.DOT_ALL),this}sticky(){return this.flags.add(r.STICKY),this}unicodeChar(t){this.flags.add(r.UNICODE);const e=new Set(["u","l","t","m","o"]);if(void 0!==t&&!e.has(t))throw new Error(`Invalid Unicode letter variant: ${t}`);return this.add(`\\p{L${null!=t?t:""}}`)}unicodeDigit(){return this.flags.add(r.UNICODE),this.add("\\p{N}")}unicodePunctuation(){return this.flags.add(r.UNICODE),this.add("\\p{P}")}unicodeSymbol(){return this.flags.add(r.UNICODE),this.add("\\p{S}")}repeat(t){if(0===this.parts.length)throw new Error("No pattern to repeat");const r=this.parts.pop();return this.parts.push(`(${r}){${t}}`),this}ipv4Octet(){return this.add("(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)")}protocol(){return this.add("https?://")}www(){return this.add("(www\\.)?")}tld(){return this.add("(com|org|net)")}path(){return this.add("(/\\w+)*")}add(t){return this.parts.push(t),this}toString(){return this.parts.join("")}toRegExp(){return new RegExp(this.toString(),[...this.flags].join(""))}}const d=()=>new n,i=(()=>{const t=t=>{const r=t().toRegExp();return()=>new RegExp(r.source,r.flags)};return{email:t((()=>d().startAnchor().word().oneOrMore().literal("@").word().oneOrMore().startGroup().literal(".").word().oneOrMore().endGroup().zeroOrMore().literal(".").letter().atLeast(2).endAnchor())),url:t((()=>d().startAnchor().protocol().www().word().oneOrMore().literal(".").tld().path().endAnchor())),phoneInternational:t((()=>d().startAnchor().literal("+").digit().between(1,3).literal("-").digit().between(3,14).endAnchor()))}})();export{r as Flags,i as Patterns,a as Quantifiers,e as Ranges,d as createRegex}; -+const t=new Map,r={GLOBAL:"g",NON_SENSITIVE:"i",MULTILINE:"m",DOT_ALL:"s",UNICODE:"u",STICKY:"y"},e=Object.freeze({digit:"0-9",lowercaseLetter:"a-z",uppercaseLetter:"A-Z",letter:"a-zA-Z",alphanumeric:"a-zA-Z0-9",anyCharacter:"."}),n=Object.freeze({zeroOrMore:"*",oneOrMore:"+",optional:"?"});class a{constructor(){this.parts=[],this.flags=new Set}digit(){return this.add("\\d")}special(){return this.add("(?=.*[!@#$%^&*])")}word(){return this.add("\\w")}whitespace(){return this.add("\\s")}nonWhitespace(){return this.add("\\S")}literal(r){return this.add(function(r){t.has(r)||t.set(r,r.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"));return t.get(r)}(r))}or(){return this.add("|")}range(t){const r=e[t];if(!r)throw new Error(`Unknown range: ${t}`);return this.add(`[${r}]`)}notRange(t){const r=e[t];if(!r)throw new Error(`Unknown range: ${t}`);return this.add(`[^${r}]`)}anyOf(t){return this.add(`[${t}]`)}notAnyOf(t){return this.add(`[^${t}]`)}lazy(){const t=this.parts.pop();if(!t)throw new Error("No quantifier to make lazy");return this.add(`${t}?`)}letter(){return this.add("[a-zA-Z]")}anyCharacter(){return this.add(".")}newline(){return this.add("(?:\\r\\n|\\r|\\n)")}negativeLookahead(t){return this.add(`(?!${t})`)}positiveLookahead(t){return this.add(`(?=${t})`)}positiveLookbehind(t){return this.add(`(?<=${t})`)}negativeLookbehind(t){return this.add(`(?`)}startGroup(){return this.add("(?:")}startCaptureGroup(){return this.add("(")}wordBoundary(){return this.add("\\b")}nonWordBoundary(){return this.add("\\B")}endGroup(){return this.add(")")}startAnchor(){return this.add("^")}endAnchor(){return this.add("$")}global(){return this.flags.add(r.GLOBAL),this}nonSensitive(){return this.flags.add(r.NON_SENSITIVE),this}multiline(){return this.flags.add(r.MULTILINE),this}dotAll(){return this.flags.add(r.DOT_ALL),this}sticky(){return this.flags.add(r.STICKY),this}unicodeChar(t){this.flags.add(r.UNICODE);const e=new Set(["u","l","t","m","o"]);if(void 0!==t&&!e.has(t))throw new Error(`Invalid Unicode letter variant: ${t}`);return this.add(`\\p{L${null!=t?t:""}}`)}unicodeDigit(){return this.flags.add(r.UNICODE),this.add("\\p{N}")}unicodePunctuation(){return this.flags.add(r.UNICODE),this.add("\\p{P}")}unicodeSymbol(){return this.flags.add(r.UNICODE),this.add("\\p{S}")}repeat(t){if(0===this.parts.length)throw new Error("No pattern to repeat");const r=this.parts.pop();return this.parts.push(`(${r}){${t}}`),this}ipv4Octet(){return this.add("(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)")}protocol(){return this.add("https?://")}www(){return this.add("(www\\.)?")}tld(){return this.add("(com|org|net)")}path(){return this.add("(/\\w+)*")}add(t){return this.parts.push(t),this}toString(){return this.parts.join("")}toRegExp(){return new RegExp(this.toString(),[...this.flags].join(""))}}const d=()=>new a,i=(()=>{const t=t=>{const r=t().toRegExp();return()=>new RegExp(r.source,r.flags)};return{email:t((()=>d().startAnchor().word().oneOrMore().literal("@").word().oneOrMore().startGroup().literal(".").word().oneOrMore().endGroup().zeroOrMore().literal(".").letter().atLeast(2).endAnchor())),url:t((()=>d().startAnchor().protocol().www().word().oneOrMore().literal(".").tld().path().endAnchor())),phoneInternational:t((()=>d().startAnchor().literal("+").digit().between(1,3).literal("-").digit().between(3,14).endAnchor()))}})();export{r as Flags,i as Patterns,n as Quantifiers,e as Ranges,d as createRegex}; - //# sourceMappingURL=human-regex.esm.js.map -diff --git a/dist/human-regex.esm.js.map b/dist/human-regex.esm.js.map -index 14d4247491ad8cf1e767e53d5b6623c4d8bc80fe..f1c0cb3734effb96175e811f8aa591cc87938638 100644 ---- a/dist/human-regex.esm.js.map -+++ b/dist/human-regex.esm.js.map -@@ -1 +1 @@ --{"version":3,"file":"human-regex.esm.js","sources":["../src/human-regex.ts"],"sourcesContent":["type PartialBut = Partial & Pick;\n\nconst escapeCache = new Map();\n\nconst Flags = {\n GLOBAL: \"g\",\n NON_SENSITIVE: \"i\",\n MULTILINE: \"m\",\n DOT_ALL: \"s\",\n UNICODE: \"u\",\n STICKY: \"y\",\n} as const;\n\nconst Ranges = Object.freeze({\n digit: \"0-9\",\n lowercaseLetter: \"a-z\",\n uppercaseLetter: \"A-Z\",\n letter: \"a-zA-Z\",\n alphanumeric: \"a-zA-Z0-9\",\n anyCharacter: \".\",\n});\n\ntype RangeKeys = keyof typeof Ranges;\n\nconst Quantifiers = Object.freeze({\n zeroOrMore: \"*\",\n oneOrMore: \"+\",\n optional: \"?\",\n});\n\ntype Quantifiers =\n | \"exactly\"\n | \"atLeast\"\n | \"atMost\"\n | \"between\"\n | \"oneOrMore\"\n | \"zeroOrMore\"\n | \"repeat\";\ntype QuantifierMethods = Quantifiers | \"optional\" | \"lazy\";\n\ntype WithLazy = HumanRegex;\ntype Base = Omit;\ntype AtStart = Omit;\ntype AfterAnchor = Omit;\ntype SimpleQuantifier = Omit;\ntype LazyQuantifier = Omit;\n\nclass HumanRegex {\n private parts: string[];\n private flags: Set;\n\n constructor() {\n this.parts = [];\n this.flags = new Set();\n }\n\n digit(): Base {\n return this.add(\"\\\\d\");\n }\n\n special(): Base {\n return this.add(\"(?=.*[!@#$%^&*])\");\n }\n\n word(): Base {\n return this.add(\"\\\\w\");\n }\n\n whitespace(): Base {\n return this.add(\"\\\\s\");\n }\n\n nonWhitespace(): Base {\n return this.add(\"\\\\S\");\n }\n\n literal(text: string): this {\n return this.add(escapeLiteral(text));\n }\n\n or(): AfterAnchor {\n return this.add(\"|\");\n }\n\n range(name: RangeKeys): Base {\n const range = Ranges[name];\n if (!range) throw new Error(`Unknown range: ${name}`);\n return this.add(`[${range}]`);\n }\n\n notRange(chars: string): Base {\n return this.add(`[^${chars}]`);\n }\n\n lazy(): Base {\n const lastPart = this.parts.pop();\n if (!lastPart) throw new Error(\"No quantifier to make lazy\");\n return this.add(`${lastPart}?`);\n }\n\n letter(): Base {\n return this.add(\"[a-zA-Z]\");\n }\n\n anyCharacter(): Base {\n return this.add(\".\");\n }\n\n negativeLookahead(pattern: string): Base {\n return this.add(`(?!${pattern})`);\n }\n\n positiveLookahead(pattern: string): Base {\n return this.add(`(?=${pattern})`);\n }\n\n positiveLookbehind(pattern: string): Base {\n return this.add(`(?<=${pattern})`);\n }\n\n negativeLookbehind(pattern: string): Base {\n return this.add(`(?`);\n }\n\n startGroup(): AfterAnchor {\n return this.add(\"(?:\");\n }\n\n startCaptureGroup(): AfterAnchor {\n return this.add(\"(\");\n }\n\n wordBoundary(): Base {\n return this.add(\"\\\\b\");\n }\n\n nonWordBoundary(): Base {\n return this.add(\"\\\\B\");\n }\n\n endGroup(): Base {\n return this.add(\")\");\n }\n\n startAnchor(): AfterAnchor {\n return this.add(\"^\");\n }\n\n endAnchor(): AfterAnchor {\n return this.add(\"$\");\n }\n\n global(): this {\n this.flags.add(Flags.GLOBAL);\n return this;\n }\n\n nonSensitive(): this {\n this.flags.add(Flags.NON_SENSITIVE);\n return this;\n }\n\n multiline(): this {\n this.flags.add(Flags.MULTILINE);\n return this;\n }\n\n dotAll(): this {\n this.flags.add(Flags.DOT_ALL);\n return this;\n }\n\n sticky(): this {\n this.flags.add(Flags.STICKY);\n return this;\n }\n\n unicodeChar(variant?: \"u\" | \"l\" | \"t\" | \"m\" | \"o\"): Base {\n this.flags.add(Flags.UNICODE);\n const validVariants = new Set([\"u\", \"l\", \"t\", \"m\", \"o\"] as const);\n\n if (variant !== undefined && !validVariants.has(variant)) {\n throw new Error(`Invalid Unicode letter variant: ${variant}`);\n }\n\n return this.add(`\\\\p{L${variant ?? \"\"}}`);\n }\n\n unicodeDigit(): Base {\n this.flags.add(Flags.UNICODE);\n return this.add(\"\\\\p{N}\");\n }\n\n unicodePunctuation(): Base {\n this.flags.add(Flags.UNICODE);\n return this.add(\"\\\\p{P}\");\n }\n\n unicodeSymbol(): Base {\n this.flags.add(Flags.UNICODE);\n return this.add(\"\\\\p{S}\");\n }\n\n repeat(count: number): Base {\n if (this.parts.length === 0) {\n throw new Error(\"No pattern to repeat\");\n }\n\n const lastPart = this.parts.pop();\n this.parts.push(`(${lastPart}){${count}}`);\n return this;\n }\n\n ipv4Octet(): Base {\n return this.add(\"(25[0-5]|2[0-4]\\\\d|1\\\\d\\\\d|[1-9]\\\\d|\\\\d)\");\n }\n\n protocol(): Base {\n return this.add(\"https?://\");\n }\n\n www(): Base {\n return this.add(\"(www\\\\.)?\");\n }\n\n tld(): Base {\n return this.add(\"(com|org|net)\");\n }\n\n path(): Base {\n return this.add(\"(/\\\\w+)*\");\n }\n\n private add(part: string): this {\n this.parts.push(part);\n return this;\n }\n\n toString(): string {\n return this.parts.join(\"\");\n }\n\n toRegExp(): RegExp {\n return new RegExp(this.toString(), [...this.flags].join(\"\"));\n }\n}\n\nfunction escapeLiteral(text: string): string {\n if (!escapeCache.has(text)) {\n escapeCache.set(text, text.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\"));\n }\n return escapeCache.get(text)!;\n}\n\nconst createRegex = (): AtStart => new HumanRegex();\n\nconst Patterns = (() => {\n const createCachedPattern = (\n builder: () => PartialBut\n ) => {\n const regex = builder().toRegExp();\n return () => new RegExp(regex.source, regex.flags);\n };\n\n return {\n email: createCachedPattern(() =>\n createRegex()\n .startAnchor()\n .word()\n .oneOrMore()\n .literal(\"@\")\n .word()\n .oneOrMore()\n .startGroup()\n .literal(\".\")\n .word()\n .oneOrMore()\n .endGroup()\n .zeroOrMore()\n .literal(\".\")\n .letter()\n .atLeast(2)\n .endAnchor()\n ),\n url: createCachedPattern(() =>\n createRegex()\n .startAnchor()\n .protocol()\n .www()\n .word()\n .oneOrMore()\n .literal(\".\")\n .tld()\n .path()\n .endAnchor()\n ),\n phoneInternational: createCachedPattern(() =>\n createRegex()\n .startAnchor()\n .literal(\"+\")\n .digit()\n .between(1, 3)\n .literal(\"-\")\n .digit()\n .between(3, 14)\n .endAnchor()\n ),\n };\n})();\n\nexport { createRegex, Patterns, Flags, Ranges, Quantifiers };\n"],"names":["escapeCache","Map","Flags","GLOBAL","NON_SENSITIVE","MULTILINE","DOT_ALL","UNICODE","STICKY","Ranges","Object","freeze","digit","lowercaseLetter","uppercaseLetter","letter","alphanumeric","anyCharacter","Quantifiers","zeroOrMore","oneOrMore","optional","HumanRegex","constructor","this","parts","flags","Set","add","special","word","whitespace","nonWhitespace","literal","text","has","set","replace","get","escapeLiteral","or","range","name","Error","notRange","chars","lazy","lastPart","pop","negativeLookahead","pattern","positiveLookahead","positiveLookbehind","negativeLookbehind","hasSpecialCharacter","hasDigit","hasLetter","exactly","n","atLeast","atMost","between","min","max","startNamedGroup","startGroup","startCaptureGroup","wordBoundary","nonWordBoundary","endGroup","startAnchor","endAnchor","global","nonSensitive","multiline","dotAll","sticky","unicodeChar","variant","validVariants","undefined","unicodeDigit","unicodePunctuation","unicodeSymbol","repeat","count","length","push","ipv4Octet","protocol","www","tld","path","part","toString","join","toRegExp","RegExp","createRegex","Patterns","createCachedPattern","builder","regex","source","email","url","phoneInternational"],"mappings":"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"} -\ No newline at end of file -+{"version":3,"file":"human-regex.esm.js","sources":["../src/human-regex.ts"],"sourcesContent":["type PartialBut = Partial & Pick;\n\nconst escapeCache = new Map();\n\nconst Flags = {\n GLOBAL: \"g\",\n NON_SENSITIVE: \"i\",\n MULTILINE: \"m\",\n DOT_ALL: \"s\",\n UNICODE: \"u\",\n STICKY: \"y\",\n} as const;\n\nconst Ranges = Object.freeze({\n digit: \"0-9\",\n lowercaseLetter: \"a-z\",\n uppercaseLetter: \"A-Z\",\n letter: \"a-zA-Z\",\n alphanumeric: \"a-zA-Z0-9\",\n anyCharacter: \".\",\n});\n\ntype RangeKeys = keyof typeof Ranges;\n\nconst Quantifiers = Object.freeze({\n zeroOrMore: \"*\",\n oneOrMore: \"+\",\n optional: \"?\",\n});\n\ntype Quantifiers =\n | \"exactly\"\n | \"atLeast\"\n | \"atMost\"\n | \"between\"\n | \"oneOrMore\"\n | \"zeroOrMore\"\n | \"repeat\";\ntype QuantifierMethods = Quantifiers | \"optional\" | \"lazy\";\n\ntype WithLazy = HumanRegex;\ntype Base = Omit;\ntype AtStart = Omit;\ntype AfterAnchor = Omit;\ntype SimpleQuantifier = Omit;\ntype LazyQuantifier = Omit;\n\nclass HumanRegex {\n private parts: string[];\n private flags: Set;\n\n constructor() {\n this.parts = [];\n this.flags = new Set();\n }\n\n digit(): Base {\n return this.add(\"\\\\d\");\n }\n\n special(): Base {\n return this.add(\"(?=.*[!@#$%^&*])\");\n }\n\n word(): Base {\n return this.add(\"\\\\w\");\n }\n\n whitespace(): Base {\n return this.add(\"\\\\s\");\n }\n\n nonWhitespace(): Base {\n return this.add(\"\\\\S\");\n }\n\n literal(text: string): this {\n return this.add(escapeLiteral(text));\n }\n\n or(): AfterAnchor {\n return this.add(\"|\");\n }\n\n range(name: RangeKeys): Base {\n const range = Ranges[name];\n if (!range) throw new Error(`Unknown range: ${name}`);\n return this.add(`[${range}]`);\n }\n\n notRange(name: RangeKeys): Base {\n const range = Ranges[name];\n if (!range) throw new Error(`Unknown range: ${name}`);\n return this.add(`[^${range}]`);\n }\n\n anyOf(chars: string): Base {\n return this.add(`[${chars}]`);\n }\n\n notAnyOf(chars: string): Base {\n return this.add(`[^${chars}]`);\n }\n\n lazy(): Base {\n const lastPart = this.parts.pop();\n if (!lastPart) throw new Error(\"No quantifier to make lazy\");\n return this.add(`${lastPart}?`);\n }\n\n letter(): Base {\n return this.add(\"[a-zA-Z]\");\n }\n\n anyCharacter(): Base {\n return this.add(\".\");\n }\n\n newline(): Base {\n return this.add(\"(?:\\\\r\\\\n|\\\\r|\\\\n)\"); // Windows: \\r\\n, Unix: \\n, Old Macs: \\r\n }\n\n negativeLookahead(pattern: string): Base {\n return this.add(`(?!${pattern})`);\n }\n\n positiveLookahead(pattern: string): Base {\n return this.add(`(?=${pattern})`);\n }\n\n positiveLookbehind(pattern: string): Base {\n return this.add(`(?<=${pattern})`);\n }\n\n negativeLookbehind(pattern: string): Base {\n return this.add(`(?`);\n }\n\n startGroup(): AfterAnchor {\n return this.add(\"(?:\");\n }\n\n startCaptureGroup(): AfterAnchor {\n return this.add(\"(\");\n }\n\n wordBoundary(): Base {\n return this.add(\"\\\\b\");\n }\n\n nonWordBoundary(): Base {\n return this.add(\"\\\\B\");\n }\n\n endGroup(): Base {\n return this.add(\")\");\n }\n\n startAnchor(): AfterAnchor {\n return this.add(\"^\");\n }\n\n endAnchor(): AfterAnchor {\n return this.add(\"$\");\n }\n\n global(): this {\n this.flags.add(Flags.GLOBAL);\n return this;\n }\n\n nonSensitive(): this {\n this.flags.add(Flags.NON_SENSITIVE);\n return this;\n }\n\n multiline(): this {\n this.flags.add(Flags.MULTILINE);\n return this;\n }\n\n dotAll(): this {\n this.flags.add(Flags.DOT_ALL);\n return this;\n }\n\n sticky(): this {\n this.flags.add(Flags.STICKY);\n return this;\n }\n\n unicodeChar(variant?: \"u\" | \"l\" | \"t\" | \"m\" | \"o\"): Base {\n this.flags.add(Flags.UNICODE);\n const validVariants = new Set([\"u\", \"l\", \"t\", \"m\", \"o\"] as const);\n\n if (variant !== undefined && !validVariants.has(variant)) {\n throw new Error(`Invalid Unicode letter variant: ${variant}`);\n }\n\n return this.add(`\\\\p{L${variant ?? \"\"}}`);\n }\n\n unicodeDigit(): Base {\n this.flags.add(Flags.UNICODE);\n return this.add(\"\\\\p{N}\");\n }\n\n unicodePunctuation(): Base {\n this.flags.add(Flags.UNICODE);\n return this.add(\"\\\\p{P}\");\n }\n\n unicodeSymbol(): Base {\n this.flags.add(Flags.UNICODE);\n return this.add(\"\\\\p{S}\");\n }\n\n repeat(count: number): Base {\n if (this.parts.length === 0) {\n throw new Error(\"No pattern to repeat\");\n }\n\n const lastPart = this.parts.pop();\n this.parts.push(`(${lastPart}){${count}}`);\n return this;\n }\n\n ipv4Octet(): Base {\n return this.add(\"(25[0-5]|2[0-4]\\\\d|1\\\\d\\\\d|[1-9]\\\\d|\\\\d)\");\n }\n\n protocol(): Base {\n return this.add(\"https?://\");\n }\n\n www(): Base {\n return this.add(\"(www\\\\.)?\");\n }\n\n tld(): Base {\n return this.add(\"(com|org|net)\");\n }\n\n path(): Base {\n return this.add(\"(/\\\\w+)*\");\n }\n\n private add(part: string): this {\n this.parts.push(part);\n return this;\n }\n\n toString(): string {\n return this.parts.join(\"\");\n }\n\n toRegExp(): RegExp {\n return new RegExp(this.toString(), [...this.flags].join(\"\"));\n }\n}\n\nfunction escapeLiteral(text: string): string {\n if (!escapeCache.has(text)) {\n escapeCache.set(text, text.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\"));\n }\n return escapeCache.get(text)!;\n}\n\nconst createRegex = (): AtStart => new HumanRegex();\n\nconst Patterns = (() => {\n const createCachedPattern = (\n builder: () => PartialBut\n ) => {\n const regex = builder().toRegExp();\n return () => new RegExp(regex.source, regex.flags);\n };\n\n return {\n email: createCachedPattern(() =>\n createRegex()\n .startAnchor()\n .word()\n .oneOrMore()\n .literal(\"@\")\n .word()\n .oneOrMore()\n .startGroup()\n .literal(\".\")\n .word()\n .oneOrMore()\n .endGroup()\n .zeroOrMore()\n .literal(\".\")\n .letter()\n .atLeast(2)\n .endAnchor()\n ),\n url: createCachedPattern(() =>\n createRegex()\n .startAnchor()\n .protocol()\n .www()\n .word()\n .oneOrMore()\n .literal(\".\")\n .tld()\n .path()\n .endAnchor()\n ),\n phoneInternational: createCachedPattern(() =>\n createRegex()\n .startAnchor()\n .literal(\"+\")\n .digit()\n .between(1, 3)\n .literal(\"-\")\n .digit()\n .between(3, 14)\n .endAnchor()\n ),\n };\n})();\n\nexport { createRegex, Patterns, Flags, Ranges, Quantifiers };\n"],"names":["escapeCache","Map","Flags","GLOBAL","NON_SENSITIVE","MULTILINE","DOT_ALL","UNICODE","STICKY","Ranges","Object","freeze","digit","lowercaseLetter","uppercaseLetter","letter","alphanumeric","anyCharacter","Quantifiers","zeroOrMore","oneOrMore","optional","HumanRegex","constructor","this","parts","flags","Set","add","special","word","whitespace","nonWhitespace","literal","text","has","set","replace","get","escapeLiteral","or","range","name","Error","notRange","anyOf","chars","notAnyOf","lazy","lastPart","pop","newline","negativeLookahead","pattern","positiveLookahead","positiveLookbehind","negativeLookbehind","hasSpecialCharacter","hasDigit","hasLetter","exactly","n","atLeast","atMost","between","min","max","startNamedGroup","startGroup","startCaptureGroup","wordBoundary","nonWordBoundary","endGroup","startAnchor","endAnchor","global","nonSensitive","multiline","dotAll","sticky","unicodeChar","variant","validVariants","undefined","unicodeDigit","unicodePunctuation","unicodeSymbol","repeat","count","length","push","ipv4Octet","protocol","www","tld","path","part","toString","join","toRegExp","RegExp","createRegex","Patterns","createCachedPattern","builder","regex","source","email","url","phoneInternational"],"mappings":"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"} -\ No newline at end of file -diff --git a/index.d.ts b/index.d.ts -index 87eacee3c4aad3e1c79fb06dcf60319065012b97..de4a228088e210651918cb87a697285d00f0da40 100644 ---- a/index.d.ts -+++ b/index.d.ts -@@ -63,10 +63,13 @@ export class HumanRegex { - or(): AfterAnchor; - - range(name: RangeKeys): Base; -- notRange(chars: string): Base; -+ notRange(name: RangeKeys): Base; -+ anyOf(chars: string): Base; -+ notAnyOf(chars: string): Base; - lazy(): Base; - letter(): Base; - anyCharacter(): Base; -+ newline(): Base; - - // Lookahead/behind - negativeLookahead(pattern: string): Base; -diff --git a/package.json b/package.json -index 881d37da1ce741e0b7a82da9163d2718de53151f..214261c20aca7213c4955e71179fd3d33a428810 100644 ---- a/package.json -+++ b/package.json -@@ -4,6 +4,13 @@ - "description": "Human-friendly regex builder with English-like syntax", - "main": "dist/human-regex.cjs.js", - "module": "dist/human-regex.esm.js", -+ "exports": { -+ ".": { -+ "import": "./dist/human-regex.esm.js", -+ "require": "./dist/human-regex.cjs.js", -+ "types": "./index.d.ts" -+ } -+ }, - "types": "types/index.d.ts", - "type": "module", - "scripts": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fb12809..67c1089 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4,11 +4,6 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false -patchedDependencies: - human-regex@2.1.5: - hash: 6d6bd9e233f99785a7c2187fd464edc114b76d47001dbb4eb6b5d72168de7460 - path: patches/human-regex@2.1.5.patch - importers: .: @@ -17,10 +12,10 @@ importers: specifier: 7.0.1 version: 7.0.1 smol-toml: - specifier: ^1.5.2 + specifier: 1.5.2 version: 1.5.2 yalps: - specifier: ^0.6.3 + specifier: 0.6.3 version: 0.6.3 devDependencies: '@eslint/compat': @@ -36,7 +31,7 @@ importers: specifier: 6.2.2 version: 6.2.2 '@types/js-yaml': - specifier: ^4.0.9 + specifier: 4.0.9 version: 4.0.9 '@types/node': specifier: 22.19.0 @@ -63,8 +58,8 @@ importers: specifier: 16.5.0 version: 16.5.0 human-regex: - specifier: 2.1.5 - version: 2.1.5(patch_hash=6d6bd9e233f99785a7c2187fd464edc114b76d47001dbb4eb6b5d72168de7460) + specifier: 2.2.0 + version: 2.2.0 prettier: specifier: 3.6.2 version: 3.6.2 @@ -1605,8 +1600,8 @@ packages: html-void-elements@3.0.0: resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==} - human-regex@2.1.5: - resolution: {integrity: sha512-0IjS3kUvWMu27q4JT1t/0eA8J78iOEsn6igZ4yElBmYeyAU901+4cwQHKUyco1A2e9llO8pnIsPimPD5y+n06A==} + human-regex@2.2.0: + resolution: {integrity: sha512-lpDOVu5sVKVylCvnSG4RlhCY+9/iT0OSflkm0t6ApZ4B6wrfmHALwfifZTB7Awdjq7Xb1IR1CXgP/ecxQ7ZwrQ==} human-signals@8.0.1: resolution: {integrity: sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==} @@ -3934,7 +3929,7 @@ snapshots: html-void-elements@3.0.0: {} - human-regex@2.1.5(patch_hash=6d6bd9e233f99785a7c2187fd464edc114b76d47001dbb4eb6b5d72168de7460): + human-regex@2.2.0: dependencies: tslib: 2.8.1 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index bc2bc56..06ac931 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -3,6 +3,3 @@ packages: onlyBuiltDependencies: - esbuild - -patchedDependencies: - human-regex@2.1.5: patches/human-regex@2.1.5.patch diff --git a/src/parser_helpers.ts b/src/parser_helpers.ts index 777624c..ac20460 100644 --- a/src/parser_helpers.ts +++ b/src/parser_helpers.ts @@ -341,7 +341,7 @@ export function extractMetadata(content: string): MetadataExtract { let servings: number | undefined = undefined; // Is there front-matter at all? - const metadataContent = content.match(metadataRegex)?.[1]; + const metadataContent = content.match(metadataRegex)?.[2]; if (!metadataContent) { return { metadata }; }