diff --git a/src/compiler/build/build-finish.ts b/src/compiler/build/build-finish.ts index 91c0016b5cf2..b52919f782ea 100644 --- a/src/compiler/build/build-finish.ts +++ b/src/compiler/build/build-finish.ts @@ -1,5 +1,4 @@ -import { isFunction, isRemoteUrl } from '@utils'; -import { relative } from 'path'; +import { isFunction, isRemoteUrl, relative } from '@utils'; import type * as d from '../../declarations'; import { IS_NODE_ENV } from '../sys/environment'; diff --git a/src/compiler/output-targets/dist-collection/index.ts b/src/compiler/output-targets/dist-collection/index.ts index 5433299e468d..4ad54a9d0a6e 100644 --- a/src/compiler/output-targets/dist-collection/index.ts +++ b/src/compiler/output-targets/dist-collection/index.ts @@ -4,10 +4,11 @@ import { flatOne, generatePreamble, isOutputTargetDistCollection, + join, normalizePath, + relative, sortBy, } from '@utils'; -import { join, relative } from 'path'; import ts from 'typescript'; import type * as d from '../../../declarations'; @@ -108,10 +109,10 @@ const writeCollectionManifest = async ( outputTarget: d.OutputTargetDistCollection ) => { // get the absolute path to the directory where the collection will be saved - const collectionDir = normalizePath(outputTarget.collectionDir); + const { collectionDir } = outputTarget; // create an absolute file path to the actual collection json file - const collectionFilePath = normalizePath(join(collectionDir, COLLECTION_MANIFEST_FILE_NAME)); + const collectionFilePath = join(collectionDir, COLLECTION_MANIFEST_FILE_NAME); // don't bother serializing/writing the collection if we're not creating a distribution await compilerCtx.fs.writeFile(collectionFilePath, collectionData); diff --git a/src/compiler/output-targets/dist-custom-elements/custom-elements-types.ts b/src/compiler/output-targets/dist-custom-elements/custom-elements-types.ts index fbee63127e94..886a84e16e9e 100644 --- a/src/compiler/output-targets/dist-custom-elements/custom-elements-types.ts +++ b/src/compiler/output-targets/dist-custom-elements/custom-elements-types.ts @@ -1,5 +1,5 @@ -import { dashToPascalCase, isOutputTargetDistCustomElements, normalizePath } from '@utils'; -import { dirname, join, relative } from 'path'; +import { dashToPascalCase, isOutputTargetDistCustomElements, join, normalizePath, relative } from '@utils'; +import { dirname } from 'path'; import type * as d from '../../../declarations'; @@ -46,7 +46,7 @@ const generateCustomElementsTypesOutput = async ( const isBundleExport = outputTarget.customElementsExportBehavior === 'bundle'; // the path where we're going to write the typedef for the whole dist-custom-elements output - const customElementsDtsPath = join(outputTarget.dir!, 'index.d.ts'); + const customElementsDtsPath = normalizePath(join(outputTarget.dir!, 'index.d.ts')); // the directory where types for the individual components are written const componentsTypeDirectoryRelPath = relative(outputTarget.dir!, typesDir); diff --git a/src/compiler/output-targets/output-lazy-loader.ts b/src/compiler/output-targets/output-lazy-loader.ts index dc066335d0b9..409293097e5c 100644 --- a/src/compiler/output-targets/output-lazy-loader.ts +++ b/src/compiler/output-targets/output-lazy-loader.ts @@ -1,5 +1,4 @@ -import { generatePreamble, isOutputTargetDistLazyLoader, normalizePath, relativeImport } from '@utils'; -import { join, relative } from 'path'; +import { generatePreamble, isOutputTargetDistLazyLoader, join, relative, relativeImport } from '@utils'; import type * as d from '../../declarations'; import { getClientPolyfill } from '../app-core/app-polyfills'; @@ -49,18 +48,18 @@ const generateLoader = async ( const es2017EntryPoint = join(es2017Dir, 'loader.js'); const polyfillsEntryPoint = join(es2017Dir, 'polyfills/index.js'); const cjsEntryPoint = join(cjsDir, 'loader.cjs.js'); - const polyfillsExport = `export * from '${normalizePath(relative(loaderPath, polyfillsEntryPoint))}';`; + const polyfillsExport = `export * from '${relative(loaderPath, polyfillsEntryPoint)}';`; const indexContent = `${generatePreamble(config)} ${es5HtmlElement} ${polyfillsExport} -export * from '${normalizePath(relative(loaderPath, es5EntryPoint))}'; +export * from '${relative(loaderPath, es5EntryPoint)}'; `; const indexES2017Content = `${generatePreamble(config)} ${polyfillsExport} -export * from '${normalizePath(relative(loaderPath, es2017EntryPoint))}'; +export * from '${relative(loaderPath, es2017EntryPoint)}'; `; const indexCjsContent = `${generatePreamble(config)} -module.exports = require('${normalizePath(relative(loaderPath, cjsEntryPoint))}'); +module.exports = require('${relative(loaderPath, cjsEntryPoint)}'); module.exports.applyPolyfills = function() { return Promise.resolve() }; `; diff --git a/src/compiler/output-targets/output-www.ts b/src/compiler/output-targets/output-www.ts index 0ee9fd6527bf..c8885386e689 100644 --- a/src/compiler/output-targets/output-www.ts +++ b/src/compiler/output-targets/output-www.ts @@ -1,6 +1,5 @@ import { cloneDocument, serializeNodeToHtml } from '@stencil/core/mock-doc'; -import { catchError, flatOne, isOutputTargetWww, unique } from '@utils'; -import { join, relative } from 'path'; +import { catchError, flatOne, isOutputTargetWww, join, relative, unique } from '@utils'; import type * as d from '../../declarations'; import { generateEs5DisabledMessage } from '../app-core/app-es5-disabled'; diff --git a/src/compiler/output-targets/test/custom-elements-types.spec.ts b/src/compiler/output-targets/test/custom-elements-types.spec.ts index 5529672d1ba9..8005296586d6 100644 --- a/src/compiler/output-targets/test/custom-elements-types.spec.ts +++ b/src/compiler/output-targets/test/custom-elements-types.spec.ts @@ -5,9 +5,8 @@ import { mockModule, mockValidatedConfig, } from '@stencil/core/testing'; -import { DIST_CUSTOM_ELEMENTS } from '@utils'; +import { DIST_CUSTOM_ELEMENTS, normalizePath } from '@utils'; import path from 'path'; -import { join, relative } from 'path'; import type * as d from '../../../declarations'; import { stubComponentCompilerMeta } from '../../types/tests/ComponentCompilerMeta.stub'; @@ -29,8 +28,8 @@ const setup = () => { const buildCtx = mockBuildCtx(config, compilerCtx); const root = config.rootDir; - config.rootDir = path.join(root, 'User', 'testing', '/'); - config.globalScript = path.join(root, 'User', 'testing', 'src', 'global.ts'); + config.rootDir = normalizePath(path.join(root, 'User', 'testing', '/')); + config.globalScript = normalizePath(path.join(root, 'User', 'testing', 'src', 'global.ts')); const bundleCustomElementsSpy = jest.spyOn(outputCustomElementsMod, 'bundleCustomElements'); @@ -62,17 +61,11 @@ describe('Custom Elements Typedef generation', () => { await generateCustomElementsTypes(config, compilerCtx, buildCtx, 'types_dir'); - const componentsTypeDirectoryPath = relative('my-best-dir', join('types_dir', 'components')); - const expectedTypedefOutput = [ '/* TestApp custom elements */', - `export { StubCmp as MyComponent } from '${join(componentsTypeDirectoryPath, 'my-component', 'my-component')}';`, + `export { StubCmp as MyComponent } from '../types_dir/components/my-component/my-component';`, `export { defineCustomElement as defineCustomElementMyComponent } from './my-component';`, - `export { MyBestComponent as MyBestComponent } from '${join( - componentsTypeDirectoryPath, - 'the-other-component', - 'my-real-best-component' - )}';`, + `export { MyBestComponent as MyBestComponent } from '../types_dir/components/the-other-component/my-real-best-component';`, `export { defineCustomElement as defineCustomElementMyBestComponent } from './my-best-component';`, '', '/**', @@ -106,7 +99,7 @@ describe('Custom Elements Typedef generation', () => { '', ].join('\n'); - expect(compilerCtx.fs.writeFile).toHaveBeenCalledWith(join('my-best-dir', 'index.d.ts'), expectedTypedefOutput, { + expect(compilerCtx.fs.writeFile).toHaveBeenCalledWith('./my-best-dir/index.d.ts', expectedTypedefOutput, { outputTargetType: DIST_CUSTOM_ELEMENTS, }); @@ -165,7 +158,7 @@ describe('Custom Elements Typedef generation', () => { '', ].join('\n'); - expect(compilerCtx.fs.writeFile).toHaveBeenCalledWith(join('my-best-dir', 'index.d.ts'), expectedTypedefOutput, { + expect(compilerCtx.fs.writeFile).toHaveBeenCalledWith('./my-best-dir/index.d.ts', expectedTypedefOutput, { outputTargetType: DIST_CUSTOM_ELEMENTS, }); @@ -233,7 +226,7 @@ describe('Custom Elements Typedef generation', () => { '', ].join('\n'); - expect(compilerCtx.fs.writeFile).toHaveBeenCalledWith(join('my-best-dir', 'index.d.ts'), expectedTypedefOutput, { + expect(compilerCtx.fs.writeFile).toHaveBeenCalledWith('./my-best-dir/index.d.ts', expectedTypedefOutput, { outputTargetType: DIST_CUSTOM_ELEMENTS, }); diff --git a/src/compiler/output-targets/test/output-targets-collection.spec.ts b/src/compiler/output-targets/test/output-targets-collection.spec.ts index f88b1c6c4f0c..da1185d23fc1 100644 --- a/src/compiler/output-targets/test/output-targets-collection.spec.ts +++ b/src/compiler/output-targets/test/output-targets-collection.spec.ts @@ -1,5 +1,4 @@ import { mockBuildCtx, mockCompilerCtx, mockModule, mockValidatedConfig } from '@stencil/core/testing'; -import { normalize } from 'path'; import type * as d from '../../../declarations'; import * as test from '../../transformers/map-imports-to-path-aliases'; @@ -61,7 +60,7 @@ describe('Dist Collection output target', () => { await outputCollection(mockConfig, mockedCompilerCtx, mockedBuildCtx, changedModules); - expect(mapImportPathSpy).toHaveBeenCalledWith(mockConfig, normalize('/dist/collection/main.js'), { + expect(mapImportPathSpy).toHaveBeenCalledWith(mockConfig, '/dist/collection/main.js', { collectionDir: '/dist/collection', dir: '', transformAliasedImportPaths, diff --git a/src/compiler/prerender/prerender-queue.ts b/src/compiler/prerender/prerender-queue.ts index 3d6bb0533633..91bc0fc0c982 100644 --- a/src/compiler/prerender/prerender-queue.ts +++ b/src/compiler/prerender/prerender-queue.ts @@ -1,5 +1,4 @@ -import { buildError, catchError, isFunction, isString } from '@utils'; -import { relative } from 'path'; +import { buildError, catchError, isFunction, isString, relative } from '@utils'; import type * as d from '../../declarations'; import { crawlAnchorsForNextUrls } from './crawl-urls'; diff --git a/src/compiler/service-worker/service-worker-util.ts b/src/compiler/service-worker/service-worker-util.ts index 44a72fc8ddff..5bfdfa1ff7d9 100644 --- a/src/compiler/service-worker/service-worker-util.ts +++ b/src/compiler/service-worker/service-worker-util.ts @@ -1,10 +1,9 @@ -import { normalizePath } from '@utils'; -import { relative } from 'path'; +import { relative } from '@utils'; import type * as d from '../../declarations'; export const generateServiceWorkerUrl = (outputTarget: d.OutputTargetWww, serviceWorker: d.ServiceWorkerConfig) => { - let swUrl = normalizePath(relative(outputTarget.appDir, serviceWorker.swDest)); + let swUrl = relative(outputTarget.appDir, serviceWorker.swDest); if (swUrl.charAt(0) !== '/') { swUrl = '/' + swUrl; diff --git a/src/compiler/transformers/collections/parse-collection-module.ts b/src/compiler/transformers/collections/parse-collection-module.ts index 040db22e26e0..6196396a3cf3 100644 --- a/src/compiler/transformers/collections/parse-collection-module.ts +++ b/src/compiler/transformers/collections/parse-collection-module.ts @@ -1,5 +1,5 @@ -import { normalizePath } from '@utils'; -import { dirname, join, relative } from 'path'; +import { join, normalizePath, relative } from '@utils'; +import { dirname } from 'path'; import type * as d from '../../../declarations'; import { parseCollectionManifest } from './parse-collection-manifest'; diff --git a/src/compiler/transformers/map-imports-to-path-aliases.ts b/src/compiler/transformers/map-imports-to-path-aliases.ts index b0194b5fe5a7..c3910a0703fd 100644 --- a/src/compiler/transformers/map-imports-to-path-aliases.ts +++ b/src/compiler/transformers/map-imports-to-path-aliases.ts @@ -1,5 +1,5 @@ -import { normalizePath } from '@utils'; -import { dirname, relative } from 'path'; +import { normalizePath, relative } from '@utils'; +import { dirname } from 'path'; import ts from 'typescript'; import type * as d from '../../declarations'; diff --git a/src/compiler/transformers/rewrite-aliased-paths.ts b/src/compiler/transformers/rewrite-aliased-paths.ts index 36b406d9cb9f..42c1e6e7d565 100644 --- a/src/compiler/transformers/rewrite-aliased-paths.ts +++ b/src/compiler/transformers/rewrite-aliased-paths.ts @@ -1,5 +1,5 @@ -import { normalizePath } from '@utils'; -import { dirname, relative } from 'path'; +import { normalizePath, relative } from '@utils'; +import { dirname } from 'path'; import ts from 'typescript'; import { retrieveTsModifiers } from './transform-utils'; diff --git a/src/compiler/transformers/static-to-meta/component.ts b/src/compiler/transformers/static-to-meta/component.ts index 447c226a3527..284a2f8e17c7 100644 --- a/src/compiler/transformers/static-to-meta/component.ts +++ b/src/compiler/transformers/static-to-meta/component.ts @@ -1,5 +1,5 @@ -import { normalizePath, unique } from '@utils'; -import { dirname, isAbsolute, join, relative } from 'path'; +import { join, normalizePath, relative, unique } from '@utils'; +import { dirname, isAbsolute } from 'path'; import ts from 'typescript'; import type * as d from '../../../declarations'; diff --git a/src/compiler/transformers/stencil-import-path.ts b/src/compiler/transformers/stencil-import-path.ts index 9323999cece8..7430e9728d1c 100644 --- a/src/compiler/transformers/stencil-import-path.ts +++ b/src/compiler/transformers/stencil-import-path.ts @@ -1,5 +1,5 @@ -import { DEFAULT_STYLE_MODE, isString, normalizePath } from '@utils'; -import { basename, dirname, isAbsolute, relative } from 'path'; +import { DEFAULT_STYLE_MODE, isString, relative } from '@utils'; +import { basename, dirname, isAbsolute } from 'path'; import type { ImportData, ParsedImport, SerializeImportData } from '../../declarations'; @@ -24,7 +24,6 @@ export const serializeImportPath = (data: SerializeImportData, styleImportData: if (isString(data.importerPath) && isAbsolute(data.importeePath)) { p = relative(dirname(data.importerPath), data.importeePath); } - p = normalizePath(p); if (!p.startsWith('.')) { p = './' + p; } diff --git a/src/compiler/transformers/type-library.ts b/src/compiler/transformers/type-library.ts index 2e82adcdf375..1472bbfb4087 100644 --- a/src/compiler/transformers/type-library.ts +++ b/src/compiler/transformers/type-library.ts @@ -1,5 +1,4 @@ -import { normalizePath } from '@utils'; -import path from 'path'; +import { normalizePath, relative } from '@utils'; import ts from 'typescript'; import type * as d from '../../declarations'; @@ -30,8 +29,7 @@ export function addToLibrary( checker: ts.TypeChecker, pathToTypeModule: string ): string { - pathToTypeModule = path.relative(process.cwd(), pathToTypeModule); - pathToTypeModule = normalizePath(pathToTypeModule, false); + pathToTypeModule = relative(process.cwd(), pathToTypeModule); // for now we don't make any attempt to include types in node_modules if (pathToTypeModule.startsWith('node_modules')) { diff --git a/src/compiler/transpile/run-program.ts b/src/compiler/transpile/run-program.ts index 0e11f00c39e0..b092d0811ff0 100644 --- a/src/compiler/transpile/run-program.ts +++ b/src/compiler/transpile/run-program.ts @@ -1,5 +1,12 @@ -import { getComponentsFromModules, isOutputTargetDistTypes, loadTypeScriptDiagnostics, normalizePath } from '@utils'; -import { basename, join, relative } from 'path'; +import { + getComponentsFromModules, + isOutputTargetDistTypes, + join, + loadTypeScriptDiagnostics, + normalizePath, + relative, +} from '@utils'; +import { basename } from 'path'; import ts from 'typescript'; import type * as d from '../../declarations'; diff --git a/src/compiler/transpile/validate-components.ts b/src/compiler/transpile/validate-components.ts index 2dbf304509c2..f52dc5f02185 100644 --- a/src/compiler/transpile/validate-components.ts +++ b/src/compiler/transpile/validate-components.ts @@ -1,5 +1,4 @@ -import { buildError } from '@utils'; -import { relative } from 'path'; +import { buildError, relative } from '@utils'; import type * as d from '../../declarations'; diff --git a/src/utils/index.ts b/src/utils/index.ts index b345a5cb5fcc..e7c2ace7ed87 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -8,8 +8,8 @@ export * from './logger/logger-rollup'; export * from './logger/logger-typescript'; export * from './logger/logger-utils'; export * from './message-utils'; -export * from './normalize-path'; export * from './output-target'; +export * from './path'; export * from './query-nonce-meta-tag-content'; export * from './sourcemaps'; export * from './url-paths'; diff --git a/src/utils/logger/logger-typescript.ts b/src/utils/logger/logger-typescript.ts index e55e4a61a0f9..4b4761b31d1c 100644 --- a/src/utils/logger/logger-typescript.ts +++ b/src/utils/logger/logger-typescript.ts @@ -2,7 +2,7 @@ import type { Diagnostic, DiagnosticMessageChain, Node } from 'typescript'; import type * as d from '../../declarations'; import { isIterable } from '../helpers'; -import { normalizePath } from '../normalize-path'; +import { normalizePath } from '../path'; import { splitLineBreaks } from './logger-utils'; /** diff --git a/src/utils/normalize-path.ts b/src/utils/path.ts similarity index 86% rename from src/utils/normalize-path.ts rename to src/utils/path.ts index 40cdbbf9a01a..4e8da8e2aeb4 100644 --- a/src/utils/normalize-path.ts +++ b/src/utils/path.ts @@ -1,3 +1,5 @@ +import path from 'path'; + /** * Convert Windows backslash paths to slash paths: foo\\bar ➔ foo/bar * Forward-slash paths can be used in Windows as long as they're not @@ -187,3 +189,31 @@ const enum CharacterCodes { percent = 0x25, // % slash = 0x2f, // / } + +/** + * A wrapped version of node.js' {@link path.relative} which adds our custom + * normalization logic. This solves the relative path between `from` and `to`! + * + * @throws the underlying node.js function can throw if either path is not a + * string + * @param from the path where relative resolution starts + * @param to the destination path + * @returns the resolved relative path + */ +export function relative(from: string, to: string): string { + return normalizePath(path.relative(from, to), false); +} + +/** + * A wrapped version of node.js' {@link path.join} which adds our custom + * normalization logic. This joins all the arguments (path fragments) into a + * single path. + * + * @throws the underlying node function will throw if any argument is not a + * string + * @param paths the paths to join together + * @returns a joined path! + */ +export function join(...paths: string[]): string { + return normalizePath(path.join(...paths), false); +} diff --git a/src/utils/test/normalize-path.spec.ts b/src/utils/test/normalize-path.spec.ts index 13beca381ba6..cc72fea4edf4 100644 --- a/src/utils/test/normalize-path.spec.ts +++ b/src/utils/test/normalize-path.spec.ts @@ -1,4 +1,4 @@ -import { normalizeFsPathQuery, normalizePath } from '../normalize-path'; +import { normalizeFsPathQuery, normalizePath } from '../path'; describe('normalizePath', () => { it('node module', () => {