Skip to content

Commit

Permalink
fix(sass): fix sass imports for scoped packages
Browse files Browse the repository at this point in the history
Also requires `@stencil/sass` fix in v1.3.2
Closes #2521
  • Loading branch information
adamdbradley committed Jun 19, 2020
1 parent 8d755aa commit e551be2
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 66 deletions.
22 changes: 1 addition & 21 deletions src/compiler/style/css-imports.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as d from '../../declarations';
import { basename, dirname, isAbsolute, join, relative } from 'path';
import { buildError, normalizePath } from '@utils';
import { getModuleId } from '../sys/resolve/resolve-utils';
import { parseStyleDocs } from '../docs/style-docs';
import { resolveModuleIdAsync } from '../sys/resolve/resolve-module-async';
import { stripCssComments } from './style-utils';
Expand Down Expand Up @@ -222,27 +223,6 @@ export const replaceNodeModuleUrl = (baseCssFilePath: string, moduleId: string,
return relToRoot;
};

export const getModuleId = (orgImport: string) => {
if (orgImport.startsWith('~')) {
orgImport = orgImport.substring(1);
}
const splt = orgImport.split('/');
const m = {
moduleId: null as string,
filePath: null as string,
};

if (orgImport.startsWith('@') && splt.length > 1) {
m.moduleId = splt.slice(0, 2).join('/');
m.filePath = splt.slice(2).join('/');
} else {
m.moduleId = splt[0];
m.filePath = splt.slice(1).join('/');
}

return m;
};

export const replaceImportDeclarations = (styleText: string, cssImports: d.CssImportData[], isCssEntry: boolean) => {
for (const cssImport of cssImports) {
if (isCssEntry) {
Expand Down
39 changes: 1 addition & 38 deletions src/compiler/style/test/css-imports.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as d from '@stencil/core/declarations';
import { getCssImports, getModuleId, isCssNodeModule, isLocalCssImport, replaceImportDeclarations } from '../css-imports';
import { getCssImports, isCssNodeModule, isLocalCssImport, replaceImportDeclarations } from '../css-imports';
import { mockBuildCtx, mockConfig, mockCompilerCtx } from '@stencil/core/testing';
import { normalizePath } from '@utils';
import path from 'path';
Expand Down Expand Up @@ -418,41 +418,4 @@ describe('css-imports', () => {
});
});

describe('getModuleId', () => {
it('getModuleId non-scoped ~ package', () => {
const m = getModuleId('~ionicons/dist/css/ionicons.css');
expect(m.moduleId).toBe('ionicons');
expect(m.filePath).toBe('dist/css/ionicons.css');
});

it('getModuleId non-scoped package', () => {
const m = getModuleId('ionicons/dist/css/ionicons.css');
expect(m.moduleId).toBe('ionicons');
expect(m.filePath).toBe('dist/css/ionicons.css');
});

it('getModuleId non-scoped package, no path', () => {
const m = getModuleId('ionicons');
expect(m.moduleId).toBe('ionicons');
expect(m.filePath).toBe('');
});

it('getModuleId scoped ~ package', () => {
const m = getModuleId('~@ionic/core/dist/ionic/css/ionic.css');
expect(m.moduleId).toBe('@ionic/core');
expect(m.filePath).toBe('dist/ionic/css/ionic.css');
});

it('getModuleId scoped package', () => {
const m = getModuleId('@ionic/core/dist/ionic/css/ionic.css');
expect(m.moduleId).toBe('@ionic/core');
expect(m.filePath).toBe('dist/ionic/css/ionic.css');
});

it('getModuleId scoped package, no path', () => {
const m = getModuleId('@ionic/core');
expect(m.moduleId).toBe('@ionic/core');
expect(m.filePath).toBe('');
});
});
});
41 changes: 35 additions & 6 deletions src/compiler/sys/resolve/resolve-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,45 @@ export const isStencilCoreImport = (p: string) => p.startsWith('@stencil/core');

export const shouldFetchModule = (p: string) => IS_FETCH_ENV && !IS_NODE_ENV && isNodeModulePath(p);

export const isNodeModulePath = (p: string) =>
normalizePath(p)
.split('/')
.includes('node_modules');
export const isNodeModulePath = (p: string) => normalizePath(p).split('/').includes('node_modules');

export const getModuleId = (orgImport: string) => {
if (orgImport.startsWith('~')) {
orgImport = orgImport.substring(1);
}
const splt = orgImport.split('/');
const m = {
moduleId: null as string,
filePath: null as string,
scope: null as string,
scopeSubModuleId: null as string,
};

if (orgImport.startsWith('@') && splt.length > 1) {
m.moduleId = splt.slice(0, 2).join('/');
m.filePath = splt.slice(2).join('/');
m.scope = splt[0];
m.scopeSubModuleId = splt[1];
} else {
m.moduleId = splt[0];
m.filePath = splt.slice(1).join('/');
}

return m;
};

export const getPackageDirPath = (p: string, moduleId: string) => {
const parts = normalizePath(p).split('/');
const m = getModuleId(moduleId);
for (let i = parts.length - 1; i >= 1; i--) {
if (parts[i - 1] === 'node_modules' && parts[i] === moduleId) {
return parts.slice(0, i + 1).join('/');
if (parts[i - 1] === 'node_modules') {
if (m.scope) {
if (parts[i] === m.scope && parts[i + 1] === m.scopeSubModuleId) {
return parts.slice(0, i + 2).join('/');
}
} else if (parts[i] === m.moduleId) {
return parts.slice(0, i + 1).join('/');
}
}
}
return null;
Expand Down
53 changes: 52 additions & 1 deletion src/compiler/sys/resolve/tests/resolve-module.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getStencilInternalDtsPath, getPackageDirPath, isLocalModule, isStencilCoreImport, isNodeModulePath, setPackageVersionByContent } from '../resolve-utils';
import { getModuleId, getStencilInternalDtsPath, getPackageDirPath, isLocalModule, isStencilCoreImport, isNodeModulePath, setPackageVersionByContent } from '../resolve-utils';

describe('resolve modules', () => {
const pkgVersions = new Map<string, string>();
Expand Down Expand Up @@ -35,7 +35,58 @@ describe('resolve modules', () => {
expect(getStencilInternalDtsPath('C:\\my-windowz\\')).toBe('C:/my-windowz/node_modules/@stencil/core/internal/index.d.ts');
});

describe('getModuleId', () => {
it('getModuleId non-scoped ~ package', () => {
const m = getModuleId('~ionicons/dist/css/ionicons.css');
expect(m.moduleId).toBe('ionicons');
expect(m.filePath).toBe('dist/css/ionicons.css');
expect(m.scope).toBe(null);
expect(m.scopeSubModuleId).toBe(null);
});

it('getModuleId non-scoped package', () => {
const m = getModuleId('ionicons/dist/css/ionicons.css');
expect(m.moduleId).toBe('ionicons');
expect(m.filePath).toBe('dist/css/ionicons.css');
expect(m.scope).toBe(null);
expect(m.scopeSubModuleId).toBe(null);
});

it('getModuleId non-scoped package, no path', () => {
const m = getModuleId('ionicons');
expect(m.moduleId).toBe('ionicons');
expect(m.filePath).toBe('');
expect(m.scope).toBe(null);
expect(m.scopeSubModuleId).toBe(null);
});

it('getModuleId scoped ~ package', () => {
const m = getModuleId('~@ionic/core/dist/ionic/css/ionic.css');
expect(m.moduleId).toBe('@ionic/core');
expect(m.filePath).toBe('dist/ionic/css/ionic.css');
expect(m.scope).toBe('@ionic');
expect(m.scopeSubModuleId).toBe('core');
});

it('getModuleId scoped package', () => {
const m = getModuleId('@ionic/core/dist/ionic/css/ionic.css');
expect(m.moduleId).toBe('@ionic/core');
expect(m.filePath).toBe('dist/ionic/css/ionic.css');
expect(m.scope).toBe('@ionic');
expect(m.scopeSubModuleId).toBe('core');
});

it('getModuleId scoped package, no path', () => {
const m = getModuleId('@ionic/core');
expect(m.moduleId).toBe('@ionic/core');
expect(m.filePath).toBe('');
expect(m.scope).toBe('@ionic');
expect(m.scopeSubModuleId).toBe('core');
});
});

it('getPackageDirPath', () => {
expect(getPackageDirPath('/node_modules/@my/pkg/some/path.js', '@my/pkg')).toBe('/node_modules/@my/pkg');
expect(getPackageDirPath('\\node_modules\\my-pkg\\', 'my-pkg')).toBe('/node_modules/my-pkg');
expect(getPackageDirPath('/node_modules/my-pkg/', 'my-pkg')).toBe('/node_modules/my-pkg');
expect(getPackageDirPath('/node_modules/my-pkg/some/path.js', 'my-pkg')).toBe('/node_modules/my-pkg');
Expand Down

0 comments on commit e551be2

Please sign in to comment.