From c87d42e766d02db5352671cbf074dd637bdb23e0 Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Thu, 11 May 2023 04:08:16 -0500 Subject: [PATCH] fix: don't require 'paths' object in tsconfig to alias paths (#7000) --- .changeset/dry-garlics-push.md | 5 + .../src/vite-plugin-config-alias/index.ts | 38 +++--- .../test/alias-tsconfig-baseurl-only.test.js | 123 ++++++++++++++++++ .../astro.config.mjs | 7 + .../alias-tsconfig-baseurl-only/package.json | 10 ++ .../src/components/Alias.svelte | 4 + .../src/components/Client.svelte | 2 + .../src/components/Foo.astro | 1 + .../src/components/Style.astro | 2 + .../src/pages/index.astro | 27 ++++ .../src/styles/extra.css | 3 + .../src/styles/main.css | 5 + .../src/utils/constants.js | 3 + .../src/utils/index.js | 1 + .../alias-tsconfig-baseurl-only/tsconfig.json | 5 + pnpm-lock.yaml | 17 +++ 16 files changed, 235 insertions(+), 18 deletions(-) create mode 100644 .changeset/dry-garlics-push.md create mode 100644 packages/astro/test/alias-tsconfig-baseurl-only.test.js create mode 100644 packages/astro/test/fixtures/alias-tsconfig-baseurl-only/astro.config.mjs create mode 100644 packages/astro/test/fixtures/alias-tsconfig-baseurl-only/package.json create mode 100644 packages/astro/test/fixtures/alias-tsconfig-baseurl-only/src/components/Alias.svelte create mode 100644 packages/astro/test/fixtures/alias-tsconfig-baseurl-only/src/components/Client.svelte create mode 100644 packages/astro/test/fixtures/alias-tsconfig-baseurl-only/src/components/Foo.astro create mode 100644 packages/astro/test/fixtures/alias-tsconfig-baseurl-only/src/components/Style.astro create mode 100644 packages/astro/test/fixtures/alias-tsconfig-baseurl-only/src/pages/index.astro create mode 100644 packages/astro/test/fixtures/alias-tsconfig-baseurl-only/src/styles/extra.css create mode 100644 packages/astro/test/fixtures/alias-tsconfig-baseurl-only/src/styles/main.css create mode 100644 packages/astro/test/fixtures/alias-tsconfig-baseurl-only/src/utils/constants.js create mode 100644 packages/astro/test/fixtures/alias-tsconfig-baseurl-only/src/utils/index.js create mode 100644 packages/astro/test/fixtures/alias-tsconfig-baseurl-only/tsconfig.json diff --git a/.changeset/dry-garlics-push.md b/.changeset/dry-garlics-push.md new file mode 100644 index 000000000..b350e8f41 --- /dev/null +++ b/.changeset/dry-garlics-push.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Remove 'paths' requirement for tsconfig path aliasing diff --git a/packages/astro/src/vite-plugin-config-alias/index.ts b/packages/astro/src/vite-plugin-config-alias/index.ts index b3698c834..d124dd687 100644 --- a/packages/astro/src/vite-plugin-config-alias/index.ts +++ b/packages/astro/src/vite-plugin-config-alias/index.ts @@ -13,7 +13,7 @@ const getConfigAlias = (settings: AstroSettings): Alias[] | null => { if (!tsConfig || !tsConfigPath || !tsConfig.compilerOptions) return null; const { baseUrl, paths } = tsConfig.compilerOptions; - if (!baseUrl || !paths) return null; + if (!baseUrl) return null; // resolve the base url from the configuration file directory const resolvedBaseUrl = path.resolve(path.dirname(tsConfigPath), baseUrl); @@ -21,26 +21,28 @@ const getConfigAlias = (settings: AstroSettings): Alias[] | null => { const aliases: Alias[] = []; // compile any alias expressions and push them to the list - for (const [alias, values] of Object.entries(paths)) { - /** Regular Expression used to match a given path. */ - const find = new RegExp( - `^${[...alias] - .map((segment) => - segment === '*' ? '(.+)' : segment.replace(/[\\^$*+?.()|[\]{}]/, '\\$&') - ) - .join('')}$` - ); + if (paths) { + for (const [alias, values] of Object.entries(paths)) { + /** Regular Expression used to match a given path. */ + const find = new RegExp( + `^${[...alias] + .map((segment) => + segment === '*' ? '(.+)' : segment.replace(/[\\^$*+?.()|[\]{}]/, '\\$&') + ) + .join('')}$` + ); - /** Internal index used to calculate the matching id in a replacement. */ - let matchId = 0; + /** Internal index used to calculate the matching id in a replacement. */ + let matchId = 0; - for (const value of values) { - /** String used to replace a matched path. */ - const replacement = [...normalizePath(path.resolve(resolvedBaseUrl, value))] - .map((segment) => (segment === '*' ? `$${++matchId}` : segment === '$' ? '$$' : segment)) - .join(''); + for (const value of values) { + /** String used to replace a matched path. */ + const replacement = [...normalizePath(path.resolve(resolvedBaseUrl, value))] + .map((segment) => (segment === '*' ? `$${++matchId}` : segment === '$' ? '$$' : segment)) + .join(''); - aliases.push({ find, replacement }); + aliases.push({ find, replacement }); + } } } diff --git a/packages/astro/test/alias-tsconfig-baseurl-only.test.js b/packages/astro/test/alias-tsconfig-baseurl-only.test.js new file mode 100644 index 000000000..55b7ecc37 --- /dev/null +++ b/packages/astro/test/alias-tsconfig-baseurl-only.test.js @@ -0,0 +1,123 @@ +import { expect } from 'chai'; +import * as cheerio from 'cheerio'; +import { loadFixture } from './test-utils.js'; + +describe('Aliases with tsconfig.json - baseUrl only', () => { + let fixture; + + /** + * @param {string} html + * @returns {string[]} + */ + function getLinks(html) { + let $ = cheerio.load(html); + let out = []; + $('link[rel=stylesheet]').each((i, el) => { + out.push($(el).attr('href')); + }); + return out; + } + + /** + * @param {string} href + * @returns {Promise<{ href: string; css: string; }>} + */ + async function getLinkContent(href, f = fixture) { + const css = await f.readFile(href); + return { href, css }; + } + + before(async () => { + fixture = await loadFixture({ + root: './fixtures/alias-tsconfig-baseurl-only/', + }); + }); + + describe('dev', () => { + let devServer; + + before(async () => { + devServer = await fixture.startDevServer(); + }); + + after(async () => { + await devServer.stop(); + }); + + it('can load client components', async () => { + const html = await fixture.fetch('/').then((res) => res.text()); + const $ = cheerio.load(html); + + // Should render aliased element + expect($('#client').text()).to.equal('test'); + + const scripts = $('script').toArray(); + expect(scripts.length).to.be.greaterThan(0); + }); + + it('can load via baseUrl', async () => { + const html = await fixture.fetch('/').then((res) => res.text()); + const $ = cheerio.load(html); + + expect($('#foo').text()).to.equal('foo'); + expect($('#constants-foo').text()).to.equal('foo'); + expect($('#constants-index').text()).to.equal('index'); + }); + + it('works in css @import', async () => { + const html = await fixture.fetch('/').then((res) => res.text()); + // imported css should be bundled + expect(html).to.include('#style-red'); + expect(html).to.include('#style-blue'); + }); + + it('works in components', async () => { + const html = await fixture.fetch('/').then((res) => res.text()); + const $ = cheerio.load(html); + + expect($('#alias').text()).to.equal('foo'); + }); + }); + + describe('build', () => { + before(async () => { + await fixture.build(); + }); + + it('can load client components', async () => { + const html = await fixture.readFile('/index.html'); + const $ = cheerio.load(html); + + // Should render aliased element + expect($('#client').text()).to.equal('test'); + + const scripts = $('script').toArray(); + expect(scripts.length).to.be.greaterThan(0); + }); + + it('can load via baseUrl', async () => { + const html = await fixture.readFile('/index.html'); + const $ = cheerio.load(html); + + expect($('#foo').text()).to.equal('foo'); + expect($('#constants-foo').text()).to.equal('foo'); + expect($('#constants-index').text()).to.equal('index'); + }); + + it('works in css @import', async () => { + const html = await fixture.readFile('/index.html'); + const content = await Promise.all(getLinks(html).map((href) => getLinkContent(href))); + const [{ css }] = content; + // imported css should be bundled + expect(css).to.include('#style-red'); + expect(css).to.include('#style-blue'); + }); + + it('works in components', async () => { + const html = await fixture.readFile('/index.html'); + const $ = cheerio.load(html); + + expect($('#alias').text()).to.equal('foo'); + }); + }); +}); diff --git a/packages/astro/test/fixtures/alias-tsconfig-baseurl-only/astro.config.mjs b/packages/astro/test/fixtures/alias-tsconfig-baseurl-only/astro.config.mjs new file mode 100644 index 000000000..77fdcd1b9 --- /dev/null +++ b/packages/astro/test/fixtures/alias-tsconfig-baseurl-only/astro.config.mjs @@ -0,0 +1,7 @@ +import { defineConfig } from 'astro/config'; +import svelte from '@astrojs/svelte'; + +// https://astro.build/config +export default defineConfig({ + integrations: [svelte()], +}); diff --git a/packages/astro/test/fixtures/alias-tsconfig-baseurl-only/package.json b/packages/astro/test/fixtures/alias-tsconfig-baseurl-only/package.json new file mode 100644 index 000000000..6fcb9106c --- /dev/null +++ b/packages/astro/test/fixtures/alias-tsconfig-baseurl-only/package.json @@ -0,0 +1,10 @@ +{ + "name": "@test/aliases-tsconfig-baseurl-only", + "version": "0.0.0", + "private": true, + "dependencies": { + "@astrojs/svelte": "workspace:*", + "astro": "workspace:*", + "svelte": "^3.48.0" + } +} diff --git a/packages/astro/test/fixtures/alias-tsconfig-baseurl-only/src/components/Alias.svelte b/packages/astro/test/fixtures/alias-tsconfig-baseurl-only/src/components/Alias.svelte new file mode 100644 index 000000000..e0208ecf8 --- /dev/null +++ b/packages/astro/test/fixtures/alias-tsconfig-baseurl-only/src/components/Alias.svelte @@ -0,0 +1,4 @@ + +
{foo}
diff --git a/packages/astro/test/fixtures/alias-tsconfig-baseurl-only/src/components/Client.svelte b/packages/astro/test/fixtures/alias-tsconfig-baseurl-only/src/components/Client.svelte new file mode 100644 index 000000000..2450d326a --- /dev/null +++ b/packages/astro/test/fixtures/alias-tsconfig-baseurl-only/src/components/Client.svelte @@ -0,0 +1,2 @@ + +
test
diff --git a/packages/astro/test/fixtures/alias-tsconfig-baseurl-only/src/components/Foo.astro b/packages/astro/test/fixtures/alias-tsconfig-baseurl-only/src/components/Foo.astro new file mode 100644 index 000000000..85bd9347e --- /dev/null +++ b/packages/astro/test/fixtures/alias-tsconfig-baseurl-only/src/components/Foo.astro @@ -0,0 +1 @@ +

foo

diff --git a/packages/astro/test/fixtures/alias-tsconfig-baseurl-only/src/components/Style.astro b/packages/astro/test/fixtures/alias-tsconfig-baseurl-only/src/components/Style.astro new file mode 100644 index 000000000..0d8e06ae3 --- /dev/null +++ b/packages/astro/test/fixtures/alias-tsconfig-baseurl-only/src/components/Style.astro @@ -0,0 +1,2 @@ +

i am blue

+

i am red

diff --git a/packages/astro/test/fixtures/alias-tsconfig-baseurl-only/src/pages/index.astro b/packages/astro/test/fixtures/alias-tsconfig-baseurl-only/src/pages/index.astro new file mode 100644 index 000000000..e200a9567 --- /dev/null +++ b/packages/astro/test/fixtures/alias-tsconfig-baseurl-only/src/pages/index.astro @@ -0,0 +1,27 @@ +--- +import Client from 'components/Client.svelte' +import Foo from 'components/Foo.astro'; +import StyleComp from 'components/Style.astro'; +import Alias from 'components/Alias.svelte'; +import { foo, index } from 'utils/constants'; +import 'styles/main.css'; +--- + + + + + Aliases using tsconfig + + +
+ + + + +

{foo}

+

{index}

+

style-red

+

style-blue

+
+ + diff --git a/packages/astro/test/fixtures/alias-tsconfig-baseurl-only/src/styles/extra.css b/packages/astro/test/fixtures/alias-tsconfig-baseurl-only/src/styles/extra.css new file mode 100644 index 000000000..0b41276e8 --- /dev/null +++ b/packages/astro/test/fixtures/alias-tsconfig-baseurl-only/src/styles/extra.css @@ -0,0 +1,3 @@ +#style-red { + color: red; +} \ No newline at end of file diff --git a/packages/astro/test/fixtures/alias-tsconfig-baseurl-only/src/styles/main.css b/packages/astro/test/fixtures/alias-tsconfig-baseurl-only/src/styles/main.css new file mode 100644 index 000000000..44b3310db --- /dev/null +++ b/packages/astro/test/fixtures/alias-tsconfig-baseurl-only/src/styles/main.css @@ -0,0 +1,5 @@ +@import "styles/extra.css"; + +#style-blue { + color: blue; +} diff --git a/packages/astro/test/fixtures/alias-tsconfig-baseurl-only/src/utils/constants.js b/packages/astro/test/fixtures/alias-tsconfig-baseurl-only/src/utils/constants.js new file mode 100644 index 000000000..28e8a5c17 --- /dev/null +++ b/packages/astro/test/fixtures/alias-tsconfig-baseurl-only/src/utils/constants.js @@ -0,0 +1,3 @@ +export * from '.' + +export const foo = 'foo' diff --git a/packages/astro/test/fixtures/alias-tsconfig-baseurl-only/src/utils/index.js b/packages/astro/test/fixtures/alias-tsconfig-baseurl-only/src/utils/index.js new file mode 100644 index 000000000..96896d711 --- /dev/null +++ b/packages/astro/test/fixtures/alias-tsconfig-baseurl-only/src/utils/index.js @@ -0,0 +1 @@ +export const index = 'index' diff --git a/packages/astro/test/fixtures/alias-tsconfig-baseurl-only/tsconfig.json b/packages/astro/test/fixtures/alias-tsconfig-baseurl-only/tsconfig.json new file mode 100644 index 000000000..738e8a465 --- /dev/null +++ b/packages/astro/test/fixtures/alias-tsconfig-baseurl-only/tsconfig.json @@ -0,0 +1,5 @@ +{ + "compilerOptions": { + "baseUrl": "./src" + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 94cb491ba..71fba1de2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1672,6 +1672,18 @@ importers: specifier: ^3.48.0 version: 3.58.0 + packages/astro/test/fixtures/alias-tsconfig-baseurl-only: + dependencies: + '@astrojs/svelte': + specifier: workspace:* + version: link:../../../../integrations/svelte + astro: + specifier: workspace:* + version: link:../../.. + svelte: + specifier: ^3.48.0 + version: 3.54.0 + packages/astro/test/fixtures/alias-tsconfig/deps/namespace-package: {} packages/astro/test/fixtures/api-routes: @@ -16520,6 +16532,11 @@ packages: typescript: 5.0.2 dev: false + /svelte@3.54.0: + resolution: {integrity: sha512-tdrgeJU0hob0ZWAMoKXkhcxXA7dpTg6lZGxUeko5YqvPdJBiyRspGsCwV27kIrbrqPP2WUoSV9ca0gnLlw8YzQ==} + engines: {node: '>= 8'} + dev: false + /svelte@3.58.0: resolution: {integrity: sha512-brIBNNB76mXFmU/Kerm4wFnkskBbluBDCjx/8TcpYRb298Yh2dztS2kQ6bhtjMcvUhd5ynClfwpz5h2gnzdQ1A==} engines: {node: '>= 8'}