Skip to content

Instantly share code, notes, and snippets.

@IKatsuba
Created February 15, 2024 07:49
Show Gist options
  • Save IKatsuba/bca7b20a1d7c6d94bf4105eec3aa6014 to your computer and use it in GitHub Desktop.
Save IKatsuba/bca7b20a1d7c6d94bf4105eec3aa6014 to your computer and use it in GitHub Desktop.
Create glob patterns for an Angular library with Tailwind CSS and Nx
const { createGlobPatternsForDependencies } = require('@nx/angular/tailwind');
const { join } = require('path');
const { Project } = require('ts-morph');
const { workspaceRoot } = require('nx/src/utils/workspace-root');
/**
* Get all the library imports from the given paths
* @param {string} scope
* @param {string[]} paths
* @param {Set<`${string}/${string}/${string}`>} prevImports
* @returns {`${string}/${string}/${string}`[]}
*/
function getLibraryImports(scope, paths, prevImports = new Set()) {
const project = new Project();
project.addSourceFilesAtPaths(paths.map((glob) => join(workspaceRoot, glob)));
/**
* @type {`${string}/${string}/${string}`[]}
*/
const imports = project.getSourceFiles().flatMap((sourceFile) =>
sourceFile
.getImportDeclarations()
.filter((importDeclaration) => {
const moduleSpecifier = importDeclaration.getModuleSpecifierValue();
return moduleSpecifier.startsWith(scope);
})
.map(
/**
* @param importDeclaration
* @returns {`${string}/${string}/${string}`}
*/
(importDeclaration) => importDeclaration.getModuleSpecifierValue(),
),
);
return imports.filter((importPath) => !prevImports.has(importPath));
}
/**
* Get all the library imports from the given paths recursively
* @param {string} scope
* @param {string[]} paths
* @param {Set<`${string}/${string}/${string}`>} prevImports
* @returns {`${string}/${string}/${string}`[]}
*/
function getLibraryImportsWithNodeModules(
scope,
paths,
prevImports = new Set(),
) {
const imports = getLibraryImports(scope, paths, prevImports);
if (imports.length === 0) {
return Array.from(prevImports);
}
imports.forEach((importPath) => prevImports.add(importPath));
return getLibraryImportsWithNodeModules(
scope,
imports.map((importPath) => libraryImportToGlob(importPath)),
prevImports,
);
}
/**
* Convert a library import to a glob pattern
* @param {`${string}/${string}/${string}`} libraryImport
* @returns {string}
*/
function libraryImportToGlob(libraryImport) {
const [scope, packageName, entry] = libraryImport.split('/');
return join(
'node_modules',
scope,
packageName,
'esm2022',
entry,
'**',
'*.mjs',
);
}
/**
* Create glob patterns for library imports
* @param {string} scope - The npm scope of the library
* @param {string[]} paths - Glob patterns to search for library imports
* @returns {string[]}
*/
function createGlobPatternsForLibrary(scope, paths) {
return getLibraryImportsWithNodeModules(paths).map((importPath) =>
join(workspaceRoot, libraryImportToGlob(importPath)),
);
}
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
join(__dirname, 'src/**/!(*.stories|*.spec).{ts,html}'),
...createGlobPatternsForDependencies(__dirname),
...createGlobPatternsForLibrary('@your-nmp-scope', [
'apps/**/*.ts',
'libs/**/*.ts',
]),
],
theme: {
extend: {},
},
plugins: [],
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment