|
|
- /*
- MIT License http://www.opensource.org/licenses/mit-license.php
- Author Tobias Koppers @sokra
- */
- "use strict";
-
- function globToRegExp(glob) {
- // * [^\\\/]*
- // /**/ /.+/
- // ^* \./.+ (concord special)
- // ? [^\\\/]
- // [!...] [^...]
- // [^...] [^...]
- // / [\\\/]
- // {...,...} (...|...)
- // ?(...|...) (...|...)?
- // +(...|...) (...|...)+
- // *(...|...) (...|...)*
- // @(...|...) (...|...)
- if (/^\(.+\)$/.test(glob)) {
- // allow to pass an RegExp in brackets
- return new RegExp(glob.substr(1, glob.length - 2));
- }
- const tokens = tokenize(glob);
- const process = createRoot();
- const regExpStr = tokens.map(process).join("");
- return new RegExp("^" + regExpStr + "$");
- }
-
- const SIMPLE_TOKENS = {
- "@(": "one",
- "?(": "zero-one",
- "+(": "one-many",
- "*(": "zero-many",
- "|": "segment-sep",
- "/**/": "any-path-segments",
- "**": "any-path",
- "*": "any-path-segment",
- "?": "any-char",
- "{": "or",
- "/": "path-sep",
- ",": "comma",
- ")": "closing-segment",
- "}": "closing-or"
- };
-
- function tokenize(glob) {
- return glob
- .split(
- /([@?+*]\(|\/\*\*\/|\*\*|[?*]|\[[!^]?(?:[^\]\\]|\\.)+\]|\{|,|\/|[|)}])/g
- )
- .map(item => {
- if (!item) return null;
- const t = SIMPLE_TOKENS[item];
- if (t) {
- return {
- type: t
- };
- }
- if (item[0] === "[") {
- if (item[1] === "^" || item[1] === "!") {
- return {
- type: "inverted-char-set",
- value: item.substr(2, item.length - 3)
- };
- } else {
- return {
- type: "char-set",
- value: item.substr(1, item.length - 2)
- };
- }
- }
- return {
- type: "string",
- value: item
- };
- })
- .filter(Boolean)
- .concat({
- type: "end"
- });
- }
-
- function createRoot() {
- const inOr = [];
- const process = createSeqment();
- let initial = true;
- return function(token) {
- switch (token.type) {
- case "or":
- inOr.push(initial);
- return "(";
- case "comma":
- if (inOr.length) {
- initial = inOr[inOr.length - 1];
- return "|";
- } else {
- return process(
- {
- type: "string",
- value: ","
- },
- initial
- );
- }
- case "closing-or":
- if (inOr.length === 0) throw new Error("Unmatched '}'");
- inOr.pop();
- return ")";
- case "end":
- if (inOr.length) throw new Error("Unmatched '{'");
- return process(token, initial);
- default: {
- const result = process(token, initial);
- initial = false;
- return result;
- }
- }
- };
- }
-
- function createSeqment() {
- const inSeqment = [];
- const process = createSimple();
- return function(token, initial) {
- switch (token.type) {
- case "one":
- case "one-many":
- case "zero-many":
- case "zero-one":
- inSeqment.push(token.type);
- return "(";
- case "segment-sep":
- if (inSeqment.length) {
- return "|";
- } else {
- return process(
- {
- type: "string",
- value: "|"
- },
- initial
- );
- }
- case "closing-segment": {
- const segment = inSeqment.pop();
- switch (segment) {
- case "one":
- return ")";
- case "one-many":
- return ")+";
- case "zero-many":
- return ")*";
- case "zero-one":
- return ")?";
- }
- throw new Error("Unexcepted segment " + segment);
- }
- case "end":
- if (inSeqment.length > 0) {
- throw new Error("Unmatched segment, missing ')'");
- }
- return process(token, initial);
- default:
- return process(token, initial);
- }
- };
- }
-
- function createSimple() {
- return function(token, initial) {
- switch (token.type) {
- case "path-sep":
- return "[\\\\/]+";
- case "any-path-segments":
- return "[\\\\/]+(?:(.+)[\\\\/]+)?";
- case "any-path":
- return "(.*)";
- case "any-path-segment":
- if (initial) {
- return "\\.[\\\\/]+(?:.*[\\\\/]+)?([^\\\\/]+)";
- } else {
- return "([^\\\\/]*)";
- }
- case "any-char":
- return "[^\\\\/]";
- case "inverted-char-set":
- return "[^" + token.value + "]";
- case "char-set":
- return "[" + token.value + "]";
- case "string":
- return token.value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
- case "end":
- return "";
- default:
- throw new Error("Unsupported token '" + token.type + "'");
- }
- };
- }
-
- exports.globToRegExp = globToRegExp;
|