From ce5de67a893a61d1fce4083b08dc597bb582007e Mon Sep 17 00:00:00 2001 From: Erika <3019731+Princesseuh@users.noreply.github.com> Date: Wed, 8 Nov 2023 15:29:12 +0100 Subject: [PATCH] feat(overlay): Add click to go to editor for audits (#9016) * feat(overlay): Add click to go to editor for audits * chore: changeset * chore: update compiler dep * fix: tests * Update packages/astro/src/core/compile/compile.ts Co-authored-by: Bjorn Lu * Update packages/astro/src/core/compile/compile.ts --------- Co-authored-by: Bjorn Lu --- .changeset/calm-shirts-battle.md | 5 +++ packages/astro/package.json | 2 +- packages/astro/src/core/compile/compile.ts | 1 + .../client/dev-overlay/plugins/audit.ts | 34 +++++++++++++------ .../middleware space/src/middleware.js | 4 +-- packages/astro/test/middleware.test.js | 8 ++--- packages/astro/test/partials.test.js | 2 +- packages/astro/test/units/dev/dev.test.js | 9 ++--- 8 files changed, 43 insertions(+), 22 deletions(-) create mode 100644 .changeset/calm-shirts-battle.md diff --git a/.changeset/calm-shirts-battle.md b/.changeset/calm-shirts-battle.md new file mode 100644 index 0000000000000..023e17f3b8251 --- /dev/null +++ b/.changeset/calm-shirts-battle.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Add ability to "Click to go editor" on auditted elements in the dev overlay diff --git a/packages/astro/package.json b/packages/astro/package.json index 47e1ae572b769..d1b87a79b8c39 100644 --- a/packages/astro/package.json +++ b/packages/astro/package.json @@ -121,7 +121,7 @@ "test:e2e:match": "playwright test -g" }, "dependencies": { - "@astrojs/compiler": "^2.1.0", + "@astrojs/compiler": "^2.3.0", "@astrojs/internal-helpers": "workspace:*", "@astrojs/markdown-remark": "workspace:*", "@astrojs/telemetry": "workspace:*", diff --git a/packages/astro/src/core/compile/compile.ts b/packages/astro/src/core/compile/compile.ts index 5e1cad1bed346..f270e123eba94 100644 --- a/packages/astro/src/core/compile/compile.ts +++ b/packages/astro/src/core/compile/compile.ts @@ -46,6 +46,7 @@ export async function compile({ scopedStyleStrategy: astroConfig.scopedStyleStrategy, resultScopedSlot: true, transitionsAnimationURL: 'astro/components/viewtransitions.css', + annotateSourceFile: !viteConfig.isProduction && astroConfig.experimental.devOverlay, preprocessStyle: createStylePreprocessor({ filename, viteConfig, diff --git a/packages/astro/src/runtime/client/dev-overlay/plugins/audit.ts b/packages/astro/src/runtime/client/dev-overlay/plugins/audit.ts index 6d5779facb7ad..6961e12273294 100644 --- a/packages/astro/src/runtime/client/dev-overlay/plugins/audit.ts +++ b/packages/astro/src/runtime/client/dev-overlay/plugins/audit.ts @@ -1,4 +1,4 @@ -import type { DevOverlayPlugin } from '../../../../@types/astro.js'; +import type { DevOverlayMetadata, DevOverlayPlugin } from '../../../../@types/astro.js'; import type { DevOverlayHighlight } from '../ui-library/highlight.js'; import { getIconElement } from '../ui-library/icons.js'; import { attachTooltipToHighlight, createHighlight, positionHighlight } from './utils/highlight.js'; @@ -121,15 +121,16 @@ export default { const rect = originalElement.getBoundingClientRect(); const highlight = createHighlight(rect, 'warning'); - const tooltip = buildAuditTooltip(rule); + const tooltip = buildAuditTooltip(rule, originalElement); attachTooltipToHighlight(highlight, tooltip, originalElement); canvas.append(highlight); audits.push({ highlightElement: highlight, auditedElement: originalElement as HTMLElement }); } - function buildAuditTooltip(rule: AuditRule) { + function buildAuditTooltip(rule: AuditRule, element: Element) { const tooltip = document.createElement('astro-dev-overlay-tooltip'); + tooltip.sections = [ { icon: 'warning', @@ -138,15 +139,28 @@ export default { { content: rule.message, }, - // TODO: Add a link to the file - // Needs https://github.com/withastro/compiler/pull/375 - // { - // content: '/src/somewhere/component.astro', - // clickDescription: 'Click to go to file', - // clickAction() {}, - // }, ]; + const elementFile = element.getAttribute('data-astro-source-file'); + const elementPosition = element.getAttribute('data-astro-source-loc'); + + if (elementFile) { + const elementFileWithPosition = + elementFile + (elementPosition ? ':' + elementPosition : ''); + + tooltip.sections.push({ + content: elementFileWithPosition.slice( + (window as DevOverlayMetadata).__astro_dev_overlay__.root.length - 1 // We want to keep the final slash, so minus one. + ), + clickDescription: 'Click to go to file', + async clickAction() { + // NOTE: The path here has to be absolute and without any errors (no double slashes etc) + // or Vite will silently fail to open the file. Quite annoying. + await fetch('/__open-in-editor?file=' + encodeURIComponent(elementFileWithPosition)); + }, + }); + } + return tooltip; } diff --git a/packages/astro/test/fixtures/middleware space/src/middleware.js b/packages/astro/test/fixtures/middleware space/src/middleware.js index a889569c4344d..779bc5c93930e 100644 --- a/packages/astro/test/fixtures/middleware space/src/middleware.js +++ b/packages/astro/test/fixtures/middleware space/src/middleware.js @@ -1,4 +1,4 @@ -import { sequence, defineMiddleware } from 'astro:middleware'; +import { defineMiddleware, sequence } from 'astro:middleware'; const first = defineMiddleware(async (context, next) => { if (context.request.url.includes('/lorem')) { @@ -24,7 +24,7 @@ const first = defineMiddleware(async (context, next) => { const response = await next(); const newResponse = response.clone(); const /** @type {string} */ html = await newResponse.text(); - const newhtml = html.replace('

testing

', '

it works

'); + const newhtml = html.replace('testing', 'it works'); return new Response(newhtml, { status: 200, headers: response.headers }); } else if(context.url.pathname === '/return-response-cookies') { const response = await next(); diff --git a/packages/astro/test/middleware.test.js b/packages/astro/test/middleware.test.js index 66abce3b8752e..ac30546206fe4 100644 --- a/packages/astro/test/middleware.test.js +++ b/packages/astro/test/middleware.test.js @@ -1,9 +1,9 @@ -import { loadFixture } from './test-utils.js'; import { expect } from 'chai'; import * as cheerio from 'cheerio'; -import testAdapter from './test-adapter.js'; +import { existsSync, readFileSync } from 'node:fs'; import { fileURLToPath } from 'node:url'; -import { readFileSync, existsSync } from 'node:fs'; +import testAdapter from './test-adapter.js'; +import { loadFixture } from './test-utils.js'; describe('Middleware in DEV mode', () => { /** @type {import('./test-utils').Fixture} */ @@ -77,7 +77,7 @@ describe('Middleware in DEV mode', () => { it('should be able to clone the response', async () => { let res = await fixture.fetch('/clone'); let html = await res.text(); - expect(html).to.contain('

it works

'); + expect(html).to.contain('it works'); }); it('should forward cookies set in a component when the middleware returns a new response', async () => { diff --git a/packages/astro/test/partials.test.js b/packages/astro/test/partials.test.js index 6f1b5093899cc..4474587786b63 100644 --- a/packages/astro/test/partials.test.js +++ b/packages/astro/test/partials.test.js @@ -25,7 +25,7 @@ describe('Partials', () => { it('is only the written HTML', async () => { const html = await fixture.fetch('/partials/item/').then((res) => res.text()); - expect(html.startsWith('
  • ')).to.equal(true); + expect(html.startsWith(' { container.handle(r.req, r.res); await r.done; const doc = await r.text(); - expect(doc).to.match(/

    Regular page<\/h1>/); + console.log(doc); + expect(doc).to.match(/Regular page/); expect(r.res.statusCode).to.equal(200); } { @@ -208,7 +209,7 @@ describe('dev container', () => { container.handle(r.req, r.res); await r.done; const doc = await r.text(); - expect(doc).to.match(/

    Custom 404<\/h1>/); + expect(doc).to.match(/Custom 404/); expect(r.res.statusCode).to.equal(404); } { @@ -217,7 +218,7 @@ describe('dev container', () => { container.handle(r.req, r.res); await r.done; const doc = await r.text(); - expect(doc).to.match(/

    Custom 404<\/h1>/); + expect(doc).to.match(/Custom 404/); expect(r.res.statusCode).to.equal(404); } }