'use strict'; var extglob = require('extglob'); var nanomatch = require('nanomatch'); var regexNot = require('regex-not'); var toRegex = require('to-regex'); var not; /** * Characters to use in negation regex (we want to "not" match * characters that are matched by other parsers) */ var TEXT = '([!@*?+]?\\(|\\)|\\[:?(?=.*?:?\\])|:?\\]|[*+?!^$.\\\\/])+'; var createNotRegex = function(opts) { return not || (not = textRegex(TEXT)); }; /** * Parsers */ module.exports = function(snapdragon) { var parsers = snapdragon.parser.parsers; // register nanomatch parsers snapdragon.use(nanomatch.parsers); // get references to some specific nanomatch parsers before they // are overridden by the extglob and/or parsers var escape = parsers.escape; var slash = parsers.slash; var qmark = parsers.qmark; var plus = parsers.plus; var star = parsers.star; var dot = parsers.dot; // register extglob parsers snapdragon.use(extglob.parsers); // custom micromatch parsers snapdragon.parser .use(function() { // override "notRegex" created in nanomatch parser this.notRegex = /^\!+(?!\()/; }) // reset the referenced parsers .capture('escape', escape) .capture('slash', slash) .capture('qmark', qmark) .capture('star', star) .capture('plus', plus) .capture('dot', dot) /** * Override `text` parser */ .capture('text', function() { if (this.isInside('bracket')) return; var pos = this.position(); var m = this.match(createNotRegex(this.options)); if (!m || !m[0]) return; // escape regex boundary characters and simple brackets var val = m[0].replace(/([[\]^$])/g, '\\$1'); return pos({ type: 'text', val: val }); }); }; /** * Create text regex */ function textRegex(pattern) { var notStr = regexNot.create(pattern, {contains: true, strictClose: false}); var prefix = '(?:[\\^]|\\\\|'; return toRegex(prefix + notStr + ')', {strictClose: false}); }