Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Process gitignore-style patterns in files property of package.json #116

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
28 changes: 26 additions & 2 deletions source/lib/rules/files-property.ts
Expand Up @@ -13,12 +13,15 @@ import {getJSONPropertyPosition} from '../utils';
export default (context: Context): Diagnostic[] => {
const {pkg, typingsFile} = context;

if (!Array.isArray(pkg.files)) {
const packageFiles = pkg.files;
if (!Array.isArray(packageFiles)) {
return [];
}

const normalizedTypingsFile = path.normalize(typingsFile);
const normalizedFiles = globby.sync(pkg.files as string[], {cwd: context.cwd}).map(path.normalize);

const patternProcessedPackageFiles = processGitIgnoreStylePatterns(packageFiles);
const normalizedFiles = globby.sync(patternProcessedPackageFiles, {cwd: context.cwd}).map(path.normalize);

if (normalizedFiles.includes(normalizedTypingsFile)) {
return [];
Expand All @@ -36,3 +39,24 @@ export default (context: Context): Diagnostic[] => {
}
];
};

function processGitIgnoreStylePatterns(patterns: readonly string[]): string[] {
const processedPatterns = patterns
.map(pattern => {
const [negatePatternMatch] = pattern.match(/^!+/) || [];
const negationMarkersCount = negatePatternMatch ? negatePatternMatch.length : 0;

return [
pattern
.slice(negationMarkersCount)
// Strip off `/` from the start of the pattern
.replace(/^\/+/, ''),
negationMarkersCount % 2 === 0
] as const;
})
// Only include pattern if it has an even count of negation markers
.filter(([, hasEvenCountOfNegationMarkers]) => hasEvenCountOfNegationMarkers)
.map(([processedPattern]) => processedPattern);

return [...new Set(processedPatterns)];
}
@@ -0,0 +1,3 @@
module.exports.default = (foo, bar) => {
return foo + bar;
};
@@ -0,0 +1,7 @@
{
"name": "foo",
"files": [
"!!types/index.d.ts"
],
"types": "types/index.d.ts"
}
@@ -0,0 +1,6 @@
declare const concat: {
(foo: string, bar: string): string;
(foo: number, bar: number): number;
};

export default concat;
@@ -0,0 +1,5 @@
import {expectType} from '../../../../..';
import concat from '..';

expectType<string>(concat('foo', 'bar'));
expectType<number>(concat(1, 2));
@@ -0,0 +1,6 @@
declare const concat: {
(foo: string, bar: string): string;
(foo: number, bar: number): number;
};

export default concat;
@@ -0,0 +1,3 @@
module.exports.default = (foo, bar) => {
return foo + bar;
};
@@ -0,0 +1,5 @@
import {expectType} from '../../../..';
import concat from '.';

expectType<string>(concat('foo', 'bar'));
expectType<number>(concat(1, 2));
@@ -0,0 +1,6 @@
{
"name": "foo",
"files": [
"!index.d.ts"
]
}
@@ -0,0 +1,3 @@
module.exports.default = (foo, bar) => {
return foo + bar;
};
@@ -0,0 +1,7 @@
{
"name": "foo",
"files": [
"/types/index.d.ts"
],
"types": "types/index.d.ts"
}
@@ -0,0 +1,6 @@
declare const concat: {
(foo: string, bar: string): string;
(foo: number, bar: number): number;
};

export default concat;
@@ -0,0 +1,5 @@
import {expectType} from '../../../../..';
import concat from '..';

expectType<string>(concat('foo', 'bar'));
expectType<number>(concat(1, 2));
20 changes: 20 additions & 0 deletions source/test/test.ts
Expand Up @@ -45,6 +45,26 @@ test('allow specifying folders containing typings file in `files` list', async t
verify(t, diagnostics, []);
});

test('allow specifying negative gitignore-style patterns in `files` list', async t => {
const diagnostics = await tsd({cwd: path.join(__dirname, 'fixtures/files-gitignore-patterns/negative-pattern')});

verify(t, diagnostics, [
[3, 1, 'error', 'TypeScript type definition `index.d.ts` is not part of the `files` list.'],
]);
});

test('allow specifying negated negative (positive) gitignore-style patterns in `files` list', async t => {
const diagnostics = await tsd({cwd: path.join(__dirname, 'fixtures/files-gitignore-patterns/negative-pattern-negated')});

verify(t, diagnostics, []);
});

test('allow specifying root marker (/) gitignore-style patterns in `files` list', async t => {
const diagnostics = await tsd({cwd: path.join(__dirname, 'fixtures/files-gitignore-patterns/root-marker-pattern')});

verify(t, diagnostics, []);
});

test('allow specifying glob patterns containing typings file in `files` list', async t => {
const diagnostics = await tsd({cwd: path.join(__dirname, 'fixtures/files-glob')});

Expand Down