diff --git a/e2e/cypress.config.ts b/e2e/cypress.config.ts index 91fc313040..0c0d5f6ff6 100644 --- a/e2e/cypress.config.ts +++ b/e2e/cypress.config.ts @@ -2,7 +2,7 @@ import { defineConfig } from 'cypress' export default defineConfig({ e2e: { - baseUrl: 'http://localhost:8080', + baseUrl: 'http://localhost:9080', specPattern: 'tests/**/*.cy.ts', }, env: { diff --git a/e2e/docs/.vuepress/config.ts b/e2e/docs/.vuepress/config.ts index df9dec2321..ad679e9aa3 100644 --- a/e2e/docs/.vuepress/config.ts +++ b/e2e/docs/.vuepress/config.ts @@ -12,6 +12,8 @@ export default defineUserConfig({ dest: path.join(__dirname, 'dist', E2E_BASE), + port: 9080, + head: [ ['meta', { name: 'foo', content: 'foo' }], ['meta', { name: 'bar', content: 'bar' }], diff --git a/e2e/docs/markdown/images/images.md b/e2e/docs/markdown/images/images.md new file mode 100644 index 0000000000..ce6d169902 --- /dev/null +++ b/e2e/docs/markdown/images/images.md @@ -0,0 +1,3 @@ +![logo-public](/logo.png) + +![logo-relative](./logo-relative.png) diff --git a/e2e/docs/markdown/images/logo-relative.png b/e2e/docs/markdown/images/logo-relative.png new file mode 100644 index 0000000000..ac6beaff06 Binary files /dev/null and b/e2e/docs/markdown/images/logo-relative.png differ diff --git a/e2e/package.json b/e2e/package.json index 199868f0d8..e64fdbe352 100644 --- a/e2e/package.json +++ b/e2e/package.json @@ -6,13 +6,13 @@ "scripts": { "e2e:build": "vuepress-cli build docs --clean-cache --clean-temp", "e2e:build-webpack": "E2E_BUNDLER=webpack pnpm e2e:build", - "e2e:ci:build": "pnpm e2e:build && start-server-and-test e2e:serve http-get://localhost:8088 'pnpm e2e:run --config baseUrl=http://localhost:8088'", - "e2e:ci:dev": "start-server-and-test e2e:dev http-get://127.0.0.1:8080 'pnpm e2e:run --config baseUrl=http://localhost:8080'", + "e2e:ci:build": "pnpm e2e:build && start-server-and-test e2e:serve http-get://localhost:9080 e2e:run", + "e2e:ci:dev": "start-server-and-test e2e:dev http-get://127.0.0.1:9080 e2e:run", "e2e:clean": "rimraf .vuepress/.temp .vuepress/.cache .vuepress/dist", "e2e:dev": "vuepress-cli dev docs --clean-cache --clean-temp", "e2e:dev-webpack": "E2E_BUNDLER=webpack pnpm e2e:dev", "e2e:run": "cypress run", - "e2e:serve": "anywhere -s -h localhost -p 8088 -d docs/.vuepress/dist" + "e2e:serve": "anywhere -s -h localhost -p 9080 -d docs/.vuepress/dist" }, "dependencies": { "@vuepress/bundler-vite": "workspace:*", diff --git a/e2e/tests/markdown/images.cy.ts b/e2e/tests/markdown/images.cy.ts new file mode 100644 index 0000000000..9e7388b93a --- /dev/null +++ b/e2e/tests/markdown/images.cy.ts @@ -0,0 +1,22 @@ +describe('markdown > images', () => { + it('should render images correctly', () => { + cy.visit('/markdown/images/images.html') + + cy.get('.e2e-theme-content img') + .should('have.length', 2) + .each(([el]) => { + cy.request({ url: el.src, failOnStatusCode: false }).then((res) => { + expect(res.status).to.equal(200) + expect(el.naturalWidth).to.be.greaterThan(0) + }) + }) + + cy.get('.e2e-theme-content img') + .first() + .should('have.attr', 'alt', 'logo-public') + + cy.get('.e2e-theme-content img') + .last() + .should('have.attr', 'alt', 'logo-relative') + }) +}) diff --git a/packages/bundler-vite/src/plugins/index.ts b/packages/bundler-vite/src/plugins/index.ts index 10a59f021f..396d670398 100644 --- a/packages/bundler-vite/src/plugins/index.ts +++ b/packages/bundler-vite/src/plugins/index.ts @@ -1,2 +1,3 @@ -export * from './mainPlugin.js' -export * from './userConfigPlugin.js' +export * from './vuepressMainPlugin.js' +export * from './vuepressUserConfigPlugin.js' +export * from './vuepressVuePlugin.js' diff --git a/packages/bundler-vite/src/plugins/mainPlugin.ts b/packages/bundler-vite/src/plugins/vuepressMainPlugin.ts similarity index 99% rename from packages/bundler-vite/src/plugins/mainPlugin.ts rename to packages/bundler-vite/src/plugins/vuepressMainPlugin.ts index 7c964592da..db0e5e7a4b 100644 --- a/packages/bundler-vite/src/plugins/mainPlugin.ts +++ b/packages/bundler-vite/src/plugins/vuepressMainPlugin.ts @@ -9,7 +9,7 @@ import type { AliasOptions, Connect, Plugin, UserConfig } from 'vite' /** * The main plugin to compat vuepress with vite */ -export const mainPlugin = ({ +export const vuepressMainPlugin = ({ app, isBuild, isServer, diff --git a/packages/bundler-vite/src/plugins/userConfigPlugin.ts b/packages/bundler-vite/src/plugins/vuepressUserConfigPlugin.ts similarity index 72% rename from packages/bundler-vite/src/plugins/userConfigPlugin.ts rename to packages/bundler-vite/src/plugins/vuepressUserConfigPlugin.ts index c4bd70ff93..dd01ad4818 100644 --- a/packages/bundler-vite/src/plugins/userConfigPlugin.ts +++ b/packages/bundler-vite/src/plugins/vuepressUserConfigPlugin.ts @@ -4,7 +4,9 @@ import type { ViteBundlerOptions } from '../types.js' /** * A plugin to allow user config to override vite config */ -export const userConfigPlugin = (options: ViteBundlerOptions): Plugin => ({ +export const vuepressUserConfigPlugin = ( + options: ViteBundlerOptions, +): Plugin => ({ name: 'vuepress:user-config', config: () => options.viteOptions ?? {}, }) diff --git a/packages/bundler-vite/src/plugins/vuepressVuePlugin.ts b/packages/bundler-vite/src/plugins/vuepressVuePlugin.ts new file mode 100644 index 0000000000..35d72951de --- /dev/null +++ b/packages/bundler-vite/src/plugins/vuepressVuePlugin.ts @@ -0,0 +1,58 @@ +import vuePlugin from '@vitejs/plugin-vue' +import type { Plugin } from 'vite' +import type { AssetURLOptions, AssetURLTagConfig } from 'vue/compiler-sfc' +import type { ViteBundlerOptions } from '../types.js' + +/** + * Wrapper of official vue plugin + */ +export const vuepressVuePlugin = (options: ViteBundlerOptions): Plugin => { + return vuePlugin({ + ...options.vuePluginOptions, + template: { + ...options.vuePluginOptions?.template, + transformAssetUrls: resolveTransformAssetUrls(options), + }, + }) +} + +/** + * Determine if the given `transformAssetUrls` option is `AssetURLTagConfig` + */ +const isAssetURLTagConfig = ( + transformAssetUrls: AssetURLOptions | AssetURLTagConfig, +): transformAssetUrls is AssetURLTagConfig => + Object.values(transformAssetUrls).some((val) => Array.isArray(val)) + +/** + * Resolve `template.transformAssetUrls` option from user config + */ +const resolveTransformAssetUrls = ( + options: ViteBundlerOptions, +): AssetURLOptions => { + // default transformAssetUrls option + const defaultTransformAssetUrls = { includeAbsolute: true } + + // user provided transformAssetUrls option + const { transformAssetUrls: userTransformAssetUrls } = + options.vuePluginOptions?.template ?? {} + + // if user does not provide an object as transformAssetUrls + if (typeof userTransformAssetUrls !== 'object') { + return defaultTransformAssetUrls + } + + // AssetURLTagConfig + if (isAssetURLTagConfig(userTransformAssetUrls)) { + return { + ...defaultTransformAssetUrls, + tags: userTransformAssetUrls, + } + } + + // AssetURLOptions + return { + ...defaultTransformAssetUrls, + ...userTransformAssetUrls, + } +} diff --git a/packages/bundler-vite/src/resolveViteConfig.ts b/packages/bundler-vite/src/resolveViteConfig.ts index 2bff1201ec..ee18480c1e 100644 --- a/packages/bundler-vite/src/resolveViteConfig.ts +++ b/packages/bundler-vite/src/resolveViteConfig.ts @@ -1,8 +1,11 @@ -import { default as vuePlugin } from '@vitejs/plugin-vue' import type { App } from '@vuepress/core' import type { InlineConfig } from 'vite' import { mergeConfig } from 'vite' -import { mainPlugin, userConfigPlugin } from './plugins/index.js' +import { + vuepressMainPlugin, + vuepressUserConfigPlugin, + vuepressVuePlugin, +} from './plugins/index.js' import type { ViteBundlerOptions } from './types.js' export const resolveViteConfig = async ({ @@ -25,9 +28,9 @@ export const resolveViteConfig = async ({ charset: 'utf8', }, plugins: [ - vuePlugin(options.vuePluginOptions), - mainPlugin({ app, isBuild, isServer }), - userConfigPlugin(options), + vuepressVuePlugin(options), + vuepressMainPlugin({ app, isBuild, isServer }), + vuepressUserConfigPlugin(options), ], }, // some vite options would not take effect inside a plugin, so we still need to merge them here in addition to userConfigPlugin