Skip to content

Commit

Permalink
feat: click-to-source (QwikDev#2217) (QwikDev#2319)
Browse files Browse the repository at this point in the history

Co-authored-by: Bruno Crosier <[email protected]>
  • Loading branch information
manucorporat and brunocrosier authored Dec 1, 2022
1 parent 757c5bc commit a3138a5
Show file tree
Hide file tree
Showing 8 changed files with 179 additions and 2 deletions.
19 changes: 18 additions & 1 deletion packages/qwik/src/core/render/dom/visitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import type { ValueOrPromise } from '../../util/types';
import { isPromise, promiseAll, promiseAllLazy, then } from '../../util/promises';
import { assertDefined, assertEqual, assertTrue } from '../../error/assert';
import { logWarn } from '../../util/log';
import { qDev, qSerialize } from '../../util/qdev';
import { qDev, qInspector, qSerialize, qTest } from '../../util/qdev';
import type { OnRenderFn } from '../../component/component.public';
import { directGetAttribute, directSetAttribute } from '../fast-calls';
import { SKIP_RENDER_TYPE } from '../jsx/jsx-runtime';
Expand Down Expand Up @@ -635,6 +635,16 @@ const createElm = (
elm = createElement(doc, tag, isSvg);
flags &= ~IS_HEAD;
}
if (qDev && qInspector) {
const dev = vnode.$dev$;
if (dev) {
directSetAttribute(
elm,
'data-qwik-inspector',
`${encodeURIComponent(dev.fileName)}:${dev.lineNumber}:${dev.columnNumber}`
);
}
}

vnode.$elm$ = elm;
if (isSvg && tag === 'foreignObject') {
Expand All @@ -652,6 +662,13 @@ const createElm = (
setComponentProps(elCtx, rCtx, props.props);
setQId(rCtx, elCtx);

if (qDev && !qTest) {
const symbol = renderQRL.$symbol$;
if (symbol) {
directSetAttribute(elm, 'data-qrl', symbol);
}
}

// Run mount hook
elCtx.$componentQrl$ = renderQRL;

Expand Down
10 changes: 9 additions & 1 deletion packages/qwik/src/core/render/ssr/render-ssr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import {
import type { RenderContext } from '../types';
import { assertDefined } from '../../error/assert';
import { serializeSStyle } from '../../style/qrl-styles';
import { qDev, seal } from '../../util/qdev';
import { qDev, qInspector, seal } from '../../util/qdev';
import { qError, QError_canNotRenderHTML } from '../../error/error';
import { addSignalSub, isSignal, Signal } from '../../state/signal';
import { serializeQRLs } from '../../qrl/qrl';
Expand Down Expand Up @@ -575,6 +575,14 @@ const renderNode = (
if (flags & IS_HEAD) {
openingElement += ' q:head';
}
if (qDev && qInspector && node.dev) {
const sanitizedFileName = node?.dev?.fileName?.replace(/\\/g, '/');
if (sanitizedFileName) {
openingElement += ` data-qwik-inspector="${encodeURIComponent(sanitizedFileName)}:${
node.dev.lineNumber
}:${node.dev.columnNumber}"`;
}
}
openingElement += '>';
stream.write(openingElement);

Expand Down
1 change: 1 addition & 0 deletions packages/qwik/src/core/util/qdev.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export const qDev = globalThis.qDev === true;
export const qInspector = globalThis.qInspector === true;
export const qSerialize = globalThis.qSerialize !== false;
export const qDynamicPlatform = globalThis.qDynamicPlatform !== false;
export const qTest = globalThis.qTest === true;
Expand Down
141 changes: 141 additions & 0 deletions packages/qwik/src/optimizer/src/plugins/vite-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,146 @@ document.addEventListener('qerror', ev => {
});
</script>`;

declare global {
interface Window {
__qwik_inspector_state: {
pressedKeys: string[];
hoveredElement?: EventTarget | null;
};
}
}

const DEV_QWIK_INSPECTOR = `
<style>
#qwik-inspector-overlay {
position: fixed;
background: rgba(24, 182, 246, 0.27);
pointer-events: none;
box-sizing: border-box;
border: 2px solid rgba(172, 126, 244, 0.46);
border-radius: 4px;
}
#qwik-inspector-info-popup {
position: fixed;
bottom: 10px;
right: 10px;
font-family: monospace;
background: #000000c2;
color: white;
padding: 10px 20px;
border-radius: 8px;
box-shadow: 0 20px 25px -5px rgb(0 0 0 / 34%), 0 8px 10px -6px rgb(0 0 0 / 24%);
backdrop-filter: blur(4px);
-webkit-animation: fadeOut 0.3s 3s ease-in-out forwards;
animation: fadeOut 0.3s 3s ease-in-out forwards;
}
#qwik-inspector-info-popup p {
margin: 0px;
}
@-webkit-keyframes fadeOut {
0% {opacity: 1;}
100% {opacity: 0;}
}
@keyframes fadeOut {
0% {opacity: 1;}
100% {opacity: 0; visibility: hidden;}
}
</style>
<script>
console.debug(
'Hold-press the Alt key and click on a component in order to jump directly to the source code in your IDE'
);
window.__qwik_inspector_state = {
pressedKeys: [],
};
const overlay = document.createElement('div');
overlay.id = 'qwik-inspector-overlay';
document.body.appendChild(overlay);
document.addEventListener(
'keydown',
(event) => {
if (event.code && !window.__qwik_inspector_state.pressedKeys.includes(event.code)) {
window.__qwik_inspector_state.pressedKeys.push(event.code);
}
},
{ capture: true }
);
document.addEventListener(
'keyup',
(event) => {
if (window.__qwik_inspector_state.pressedKeys.includes(event.code)) {
window.__qwik_inspector_state.pressedKeys = window.__qwik_inspector_state.pressedKeys.filter(
(key) => key !== event.code
);
hideOverlay();
}
},
{ capture: true }
);
document.addEventListener(
'mouseover',
(event) => {
if (event.target && event.target instanceof HTMLElement && event.target.dataset.qwikInspector) {
window.__qwik_inspector_state.hoveredElement = event.target;
const rect = event.target.getBoundingClientRect();
if (overlay && checkKeysArePressed(['Shift', 'Control'])) {
overlay.style.setProperty('height', rect.height + 'px');
overlay.style.setProperty('width', rect.width + 'px');
overlay.style.setProperty('top', rect.top + 'px');
overlay.style.setProperty('left', rect.left + 'px');
overlay.style.setProperty('visibility', 'visible');
}
}
},
{ capture: true }
);
document.addEventListener(
'click',
(event) => {
if (checkKeysArePressed(['Shift', 'Control'])) {
if (event.target && event.target instanceof HTMLElement) {
if (event.target.dataset.qwikInspector) {
event.preventDefault();
fetch('/__open-in-editor?file=' + event.target.dataset.qwikInspector);
}
}
}
},
{ capture: true }
);
function hideOverlay() {
const overlay = document.getElementById('qwik-inspector-overlay');
if (overlay) {
overlay.style.setProperty('height', '0px');
overlay.style.setProperty('width', '0px');
overlay.style.setProperty('visibility', 'hidden');
}
}
function checkKeysArePressed(keys) {
return keys.every((key) =>
window.__qwik_inspector_state.pressedKeys
.map((key) => key.replace(/(Left|Right)$/g, ''))
.includes(key)
);
}
window.addEventListener('resize', hideOverlay);
document.addEventListener('scroll', hideOverlay);
</script>
<div id="qwik-inspector-info-popup"><p>Ctrl + Shift + Click ✨</p></div>
`;

const PERF_WARNING = `
<script>
if (!window.__qwikViteLog) {
Expand All @@ -277,6 +417,7 @@ const END_SSR_SCRIPT = `
${DEV_ERROR_HANDLING}
${ERROR_HOST}
${PERF_WARNING}
${DEV_QWIK_INSPECTOR}
`;

function getViteDevIndexHtml(entryUrl: string, envData: Record<string, any>) {
Expand Down
5 changes: 5 additions & 0 deletions packages/qwik/src/optimizer/src/plugins/vite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -268,9 +268,11 @@ export function qwikVite(qwikViteOpts: QwikVitePluginOptions = {}): any {
if (buildMode === 'development') {
(globalThis as any).qDev = true;
const qDevKey = 'globalThis.qDev';
const qInspectorKey = 'globalThis.qInspectorKey';
const qSerializeKey = 'globalThis.qSerialize';
updatedViteConfig.define = {
[qDevKey]: viteConfig?.define?.[qDevKey] ?? true,
[qInspectorKey]: viteConfig?.define?.[qInspectorKey] ?? true,
[qSerializeKey]: viteConfig?.define?.[qSerializeKey] ?? true,
};
}
Expand Down Expand Up @@ -300,9 +302,12 @@ export function qwikVite(qwikViteOpts: QwikVitePluginOptions = {}): any {
// Test Build
const qDevKey = 'globalThis.qDev';
const qTestKey = 'globalThis.qTest';
const qInspectorKey = 'globalThis.qInspectorKey';

updatedViteConfig.define = {
[qDevKey]: true,
[qTestKey]: true,
[qInspectorKey]: false,
};
}

Expand Down
2 changes: 2 additions & 0 deletions scripts/submodule-core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ async function submoduleCoreProd(config: BuildConfig) {
// developer production builds could use core.min.js directly, or setup
// their own build tools to define the globa `qwikDev` to false
'globalThis.qDev': false,
'globalThis.qInspector': false,
'globalThis.qSerialize': false,
'globalThis.qDynamicPlatform': false,
'globalThis.qTest': false,
Expand Down Expand Up @@ -146,6 +147,7 @@ async function submoduleCoreProduction(config: BuildConfig, code: string, outPat
unused: true,
global_defs: {
'globalThis.qDev': false,
'globalThis.qInspector': false,
'globalThis.qSerialize': true,
'globalThis.qDynamicPlatform': true,
'globalThis.qTest': false,
Expand Down
2 changes: 2 additions & 0 deletions starters/dev-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ export {
define: {
'globalThis.qSerialize': true,
'globalThis.qDev': !isProd,
'globalThis.qInspector': false,
'globalThis.PORT': port,
},
plugins: [
Expand Down Expand Up @@ -196,6 +197,7 @@ export {
plugins: [...plugins, optimizer.qwikVite()],
define: {
'globalThis.qDev': !isProd,
'globalThis.qInspector': false,
'globalThis.PORT': port,
},
})
Expand Down
1 change: 1 addition & 0 deletions tsm.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ module.exports = {
globalThis.qTest = true;
globalThis.qRuntimeQrl = true;
globalThis.qDev = true;
globalThis.qInspector = false;
import * as qwikJsx from "${corePath}";`,
target: 'es2020',
loader: 'tsx',
Expand Down

0 comments on commit a3138a5

Please sign in to comment.