Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

fast-ignore

Package Overview
Dependencies
Maintainers
1
Versions
5
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

fast-ignore - npm Package Compare versions

Comparing version 1.0.0 to 1.1.0

2

dist/ignore/compile.d.ts
import type { Glob, Node, Options } from '../types';
declare const compile: (globs: Glob[], options: Options) => Node;
declare const compile: (tiers: Glob[][], options: Options) => Node;
export default compile;
/* IMPORT */
import matcher from '../glob/matcher.js';
/* MAIN */
const compile = (globs, options) => {
const compile = (tiers, options) => {
const caseSensitive = options.caseSensitive ?? false;
const root = { id: '', globstar: false, negative: false, strength: -1, match: () => false, children: [] };
for (let gi = 0, gl = globs.length; gi < gl; gi++) {
let content = globs[gi].content;
let parent = root;
content = content.replace(/\/$/, ''); //TODO: Handle this instead
content = content.replace(/(^|\/)\*\*\/(?:\*\*(\/|$))+/g, '$1**$2');
content = content.startsWith('/') ? content.slice(1) : (content.startsWith('**/') || content.slice(0, -1).includes('/') ? content : `**/${content}`);
const segments = content.split('/');
for (let si = 0, sl = segments.length; si < sl; si++) {
const id = segments[si];
const globstar = (id === '**');
const terminal = (si === sl - 1);
const negative = globs[gi].negative;
const strength = (terminal ? globs[gi].strength : -1);
const match = matcher(id, caseSensitive);
const children = [];
const node = { id, globstar, negative, strength, match, children };
const nodeExisting = parent.children.find(node => node.id === id);
if (nodeExisting) {
if (strength >= nodeExisting.strength) { // Existing weaker node, overriding it
nodeExisting.negative = negative;
nodeExisting.strength = strength;
const root = { id: '', globstar: false, negative: false, strength: -1, tier: -1, match: () => false, children: [] };
let scounter = 0;
for (let ti = 0, tl = tiers.length; ti < tl; ti++) {
const globs = tiers[ti];
const tier = ti;
for (let gi = 0, gl = globs.length; gi < gl; gi++) {
let content = globs[gi].content;
let parent = root;
content = content.replace(/\/$/, ''); //TODO: Handle this instead
content = content.replace(/(^|\/)\*\*\/(?:\*\*(\/|$))+/g, '$1**$2');
content = content.startsWith('/') ? content.slice(1) : (content.startsWith('**/') || content.slice(0, -1).includes('/') ? content : `**/${content}`);
const segments = content.split('/');
for (let si = 0, sl = segments.length; si < sl; si++) {
const id = segments[si];
const globstar = (id === '**');
const terminal = (si === sl - 1);
const negative = globs[gi].negative;
const strength = (terminal ? scounter++ : -1);
const match = matcher(id, caseSensitive);
const children = [];
const node = { id, globstar, negative, strength, tier, match, children };
const nodeExisting = parent.children.find(node => node.id === id);
if (nodeExisting) {
if ((tier === nodeExisting.tier && strength >= nodeExisting.strength) || (tier > nodeExisting.tier && (nodeExisting.strength < 0 || nodeExisting.negative))) { // Existing node, overridable by tier/strength/negativity // Basically we are making sure that files ignored in previous tiers can't be re-included back in later tiers
nodeExisting.negative = negative;
nodeExisting.strength = strength;
nodeExisting.tier = tier;
}
parent = nodeExisting;
}
parent = nodeExisting;
else {
parent.children.push(node);
parent = node;
}
}
else {
parent.children.push(node);
parent = node;
}
}

@@ -36,0 +42,0 @@ }

import type { Options } from '../types';
declare const matcher: (ignore: string, options?: Options) => (fileRelativePath: string) => boolean;
declare const matcher: (ignore: string | string[], options?: Options) => (fileRelativePath: string) => boolean;
export default matcher;

@@ -7,4 +7,5 @@ /* IMPORT */

const matcher = (ignore, options = {}) => {
const globs = parse(ignore);
const root = compile(globs, options);
const ignores = Array.isArray(ignore) ? ignore : [ignore];
const tiers = ignores.map(parse);
const root = compile(tiers, options);
const cache = []; //TODO: What is this kind of cache called??

@@ -11,0 +12,0 @@ return (fileRelativePath) => {

@@ -13,7 +13,6 @@ /* IMPORT */

const negative = content.startsWith('!');
const strength = i;
content = content.replace(/^\\(!|#)/, '$1');
content = content.replace(/((?:\\\s)*)\s*$/, ($0, $1) => $1.replaceAll('\\', ''));
content = negative ? content.slice(1) : content;
const glob = { content, negative, strength };
const glob = { content, negative };
globs.push(glob);

@@ -20,0 +19,0 @@ }

type Glob = {
content: string;
negative: boolean;
strength: number;
};

@@ -11,2 +10,3 @@ type Node = {

strength: number;
tier: number;
match: (segment: string) => boolean;

@@ -13,0 +13,0 @@ children: Node[];

@@ -5,3 +5,3 @@ {

"description": "A fast parser and processor for .gitignore files.",
"version": "1.0.0",
"version": "1.1.0",
"type": "module",

@@ -8,0 +8,0 @@ "main": "dist/index.js",

@@ -48,2 +48,24 @@ # Fast Ignore

ignore ( 'dist/foo/bar.js' ); // true
// We can also work with multiple ignore files at once, which is faster than handling them individually
// This goes roughly as fast as just concatenating the files together, but with the semantics of separate files
// The difference is that an ignore file that comes later won't be able to un-ignore something that was ignored by a previous one
// As a result please note that writing `fastIgnore ([ 'dist', '!dist' ])` may work differently than you expected
const prettierignore = `
**/test
**/__test__
# The following globs are effectively useless
# because they can't un-ignore something that was ignored by any previous ignore files
!dist
!node_modules
`;
const comboIgnore = fastIgnore ([ gitignore, prettierignore ]);
comboIgnore ( 'foo/bar.js' ); // false
comboIgnore ( 'node_modules/foo/bar.js' ); // true
comboIgnore ( 'dist/foo/bar.js' ); // true
comboIgnore ( 'test/foo/bar.js' ); // true
```

@@ -50,0 +72,0 @@

@@ -9,47 +9,57 @@

const compile = ( globs: Glob[], options: Options ): Node => {
const compile = ( tiers: Glob[][], options: Options ): Node => {
const caseSensitive = options.caseSensitive ?? false;
const root: Node = { id: '', globstar: false, negative: false, strength: -1, match: () => false, children: [] };
const root: Node = { id: '', globstar: false, negative: false, strength: -1, tier: -1, match: () => false, children: [] };
for ( let gi = 0, gl = globs.length; gi < gl; gi++ ) {
let scounter = 0;
let content = globs[gi].content;
let parent = root;
for ( let ti = 0, tl = tiers.length; ti < tl; ti++ ) {
content = content.replace ( /\/$/, '' ); //TODO: Handle this instead
content = content.replace ( /(^|\/)\*\*\/(?:\*\*(\/|$))+/g, '$1**$2' );
content = content.startsWith ( '/' ) ? content.slice ( 1 ) : ( content.startsWith ( '**/' ) || content.slice ( 0, -1 ).includes ( '/' ) ? content : `**/${content}` );
const globs = tiers[ti];
const tier = ti;
const segments = content.split ( '/' );
for ( let gi = 0, gl = globs.length; gi < gl; gi++ ) {
for ( let si = 0, sl = segments.length; si < sl; si++ ) {
let content = globs[gi].content;
let parent = root;
const id = segments[si];
const globstar = ( id === '**' );
const terminal = ( si === sl - 1 );
const negative = globs[gi].negative;
const strength = ( terminal ? globs[gi].strength : -1 );
const match = matcher ( id, caseSensitive );
const children: Node[] = [];
const node = { id, globstar, negative, strength, match, children };
const nodeExisting = parent.children.find ( node => node.id === id );
content = content.replace ( /\/$/, '' ); //TODO: Handle this instead
content = content.replace ( /(^|\/)\*\*\/(?:\*\*(\/|$))+/g, '$1**$2' );
content = content.startsWith ( '/' ) ? content.slice ( 1 ) : ( content.startsWith ( '**/' ) || content.slice ( 0, -1 ).includes ( '/' ) ? content : `**/${content}` );
if ( nodeExisting ) {
const segments = content.split ( '/' );
if ( strength >= nodeExisting.strength ) { // Existing weaker node, overriding it
for ( let si = 0, sl = segments.length; si < sl; si++ ) {
nodeExisting.negative = negative;
nodeExisting.strength = strength;
const id = segments[si];
const globstar = ( id === '**' );
const terminal = ( si === sl - 1 );
const negative = globs[gi].negative;
const strength = ( terminal ? scounter++ : -1 );
const match = matcher ( id, caseSensitive );
const children: Node[] = [];
const node = { id, globstar, negative, strength, tier, match, children };
const nodeExisting = parent.children.find ( node => node.id === id );
}
if ( nodeExisting ) {
parent = nodeExisting;
if ( ( tier === nodeExisting.tier && strength >= nodeExisting.strength ) || ( tier > nodeExisting.tier && ( nodeExisting.strength < 0 || nodeExisting.negative ) ) ) { // Existing node, overridable by tier/strength/negativity // Basically we are making sure that files ignored in previous tiers can't be re-included back in later tiers
} else {
nodeExisting.negative = negative;
nodeExisting.strength = strength;
nodeExisting.tier = tier;
parent.children.push ( node );
}
parent = node;
parent = nodeExisting;
} else {
parent.children.push ( node );
parent = node;
}
}

@@ -56,0 +66,0 @@

@@ -11,6 +11,7 @@

const matcher = ( ignore: string, options: Options = {} ): (( fileRelativePath: string ) => boolean) => {
const matcher = ( ignore: string | string[], options: Options = {} ): (( fileRelativePath: string ) => boolean) => {
const globs = parse ( ignore );
const root = compile ( globs, options );
const ignores = Array.isArray ( ignore ) ? ignore : [ignore];
const tiers = ignores.map ( parse );
const root = compile ( tiers, options );
const cache: [segment: string, [nodesNext: Node[], negative: boolean, strength: number]][] = []; //TODO: What is this kind of cache called??

@@ -17,0 +18,0 @@

@@ -21,3 +21,2 @@

const negative = content.startsWith ( '!' );
const strength = i;

@@ -28,3 +27,3 @@ content = content.replace ( /^\\(!|#)/, '$1' );

const glob = { content, negative, strength };
const glob = { content, negative };

@@ -31,0 +30,0 @@ globs.push ( glob );

@@ -6,4 +6,3 @@

content: string,
negative: boolean,
strength: number
negative: boolean
};

@@ -16,2 +15,3 @@

strength: number,
tier: number,
match: ( segment: string ) => boolean,

@@ -18,0 +18,0 @@ children: Node[]

@@ -42,4 +42,14 @@

benchmark ({
name: '.gitignore + .prettierignore',
name: '.gitignore + .prettierignore (individual)',
fn: () => {
const ignore1 = toIgnore ( gitignoreContent );
const ignore2 = toIgnore ( prettierignoreContent );
filesPaths.forEach ( ignore1 );
filesPaths.forEach ( ignore2 );
}
});
benchmark ({
name: '.gitignore + .prettierignore (concat)',
fn: () => {
const ignore = toIgnore ( comboContent );

@@ -50,2 +60,10 @@ filesPaths.forEach ( ignore );

benchmark ({
name: '.gitignore + .prettierignore (combo)',
fn: () => {
const ignore = toIgnore ([ gitignoreContent, prettierignoreContent ]);
filesPaths.forEach ( ignore );
}
});
benchmark.summary ();

@@ -107,3 +107,3 @@

it ( 'works', t => {
it ( 'works with a single tier', t => {

@@ -197,5 +197,34 @@ t.is ( ignore ( 'foo.js', 'foo.js' ), true );

// t.is ( ignore ( 'foo.js/', 'foo.js' ), true ); //TODO
// t.is ( ignore ( 'foo.js/', 'deep/foo.js' ), true ); //TODO
});
it ( 'works with multiple tiers', t => {
t.is ( ignore ( ['foo.js', 'bar.js'], 'foo.js' ), true );
t.is ( ignore ( ['foo.js', 'bar.js'], 'bar.js' ), true );
t.is ( ignore ( ['foo.js', 'bar.js'], 'baz.js' ), false );
t.is ( ignore ( ['foo.js', '!foo.js'], 'foo.js' ), true );
t.is ( ignore ( ['foo.js', '!foo.js'], 'bar.js' ), false );
t.is ( ignore ( ['foo.js', '!foo.js'], 'baz.js' ), false );
t.is ( ignore ( ['foo.js\n!foo.js', 'foo.js'], 'foo.js' ), true );
t.is ( ignore ( ['foo.js\n!foo.js', 'foo.js'], 'bar.js' ), false );
t.is ( ignore ( ['foo.js\n!foo.js', 'foo.js'], 'baz.js' ), false );
t.is ( ignore ( ['foo.js\n!foo.js', 'bar.js'], 'foo.js' ), false );
t.is ( ignore ( ['foo.js\n!foo.js', 'bar.js'], 'bar.js' ), true );
t.is ( ignore ( ['foo.js\n!foo.js', 'bar.js'], 'baz.js' ), false );
t.is ( ignore ( ['deep\n!deep', 'deep/foo.js'], 'deep/foo.js' ), true );
t.is ( ignore ( ['deep\n!deep', 'deep/foo.js'], 'deeper/deep/foo.js' ), false );
t.is ( ignore ( ['deep\n!deep', 'deep/foo.js'], 'deeper/deep/bar.js' ), false );
t.is ( ignore ( ['deep', 'deep/foo.js'], 'deep/foo.js' ), true );
t.is ( ignore ( ['deep', 'deep/foo.js'], 'deeper/deep/foo.js' ), true );
t.is ( ignore ( ['deep', 'deep/foo.js'], 'deeper/deep/bar.js' ), true );
t.is ( ignore ( ['deep', '!deep/foo.js'], 'deep/foo.js' ), true );
t.is ( ignore ( ['deep', '!deep/foo.js'], 'deeper/deep/foo.js' ), true );
t.is ( ignore ( ['deep', '!deep/foo.js'], 'deeper/deep/bar.js' ), true );
});

@@ -202,0 +231,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc