Skip to content

Commit

Permalink
feat: support goto code for nuxt
Browse files Browse the repository at this point in the history
  • Loading branch information
johnsoncodehk committed Mar 22, 2022
1 parent 77aab90 commit 4e138d4
Show file tree
Hide file tree
Showing 16 changed files with 354 additions and 418 deletions.
21 changes: 21 additions & 0 deletions extensions/vscode-vue-language-features/bin/nuxi.js
@@ -0,0 +1,21 @@
#!/usr/bin/env node

const path = require('path');
const fs = require('fs');
const readFileSync = fs.readFileSync;

const workspace = process.cwd();
const nuxiBinPath = require.resolve('./node_modules/.bin/nuxi', { paths: [workspace] });
const jsConfigPath = path.resolve(workspace, 'nuxt.config.js');
const tsConfigPath = path.resolve(workspace, 'nuxt.config.ts');

fs.readFileSync = (...args) => {
if (args[0] === jsConfigPath || args[0] === tsConfigPath) {
let configExtraContent = readFileSync(path.resolve(__dirname, 'nuxi', 'configExtraContent.ts'), { encoding: 'utf8' });
configExtraContent = configExtraContent.replace('{PLUGIN_PATH}', path.resolve(__dirname, 'nuxi', 'plugin.ts'))
return readFileSync(...args) + configExtraContent;
}
return readFileSync(...args);
};

import(nuxiBinPath);
@@ -0,0 +1,77 @@

if (!module.exports.default)
module.exports.default = {};

if (!module.exports.default.vue)
module.exports.default.vue = {};

if (!module.exports.default.vue.compilerOptions)
module.exports.default.vue.compilerOptions = {};

if (!module.exports.default.vue.compilerOptions.nodeTransforms)
module.exports.default.vue.compilerOptions.nodeTransforms = [];

module.exports.default.vue.compilerOptions.nodeTransforms.push(
(node, ctx) => {
if (node.type === 1) {
const { offset: start } = node.loc.start;
const { offset: end } = node.loc.end;
node.props.push(
{
type: 6,
name: 'data-loc',
value: {
content: `[${start},${end}]`,
},
loc: node.loc,
},
{
type: 7,
name: 'on',
exp: {
type: 4,
content: '$volar.highlight($event.target, $.type.__file, $event.target.dataset.loc);',
isStatic: false,
constType: 0,
loc: node.loc,
},
arg: {
type: 4,
content: 'mouseenter',
isStatic: true,
constType: 3,
loc: node.loc,
},
modifiers: [],
loc: node.loc,
},
{
type: 7,
name: 'on',
exp: {
type: 4,
content: '$volar.unHighlight($event.target)',
isStatic: false,
constType: 0,
loc: node.loc,
},
arg: {
type: 4,
content: 'mouseleave',
isStatic: true,
constType: 3,
loc: node.loc,
},
modifiers: [],
loc: node.loc,
},
);
}
}
);


if (!module.exports.default.plugins)
module.exports.default.plugins = [];

module.exports.default.plugins.push({ src: '{PLUGIN_PATH}', ssr: false });
176 changes: 176 additions & 0 deletions extensions/vscode-vue-language-features/bin/nuxi/plugin.ts
@@ -0,0 +1,176 @@
export default defineNuxtPlugin(app => {

if (process.server)
return;

const volar = installFinder();

let href = '';

setInterval(function () {
if (href !== location.href) {
href = location.href;
parent.postMessage({ command: 'urlChanged', data: href }, '*');
}
}, 200);

return { provide: { volar } };

function installFinder() {

window.addEventListener('scroll', updateOverlay);
window.addEventListener('message', event => {
if (event.data?.command === 'selectElement') {
enabled = true;
clickMask.style.pointerEvents = 'none';
document.body.appendChild(clickMask);
updateOverlay();
}
});
window.addEventListener('mousedown', (ev) => {
if (enabled) {
enabled = false;
clickMask.style.pointerEvents = '';
highlightNodes = [];
updateOverlay();
if (lastCodeLoc) {
parent.postMessage(lastCodeLoc, '*');
lastCodeLoc = undefined;
}
}
});

const overlay = createOverlay();
const clickMask = createClickMask();

let highlightNodes: [HTMLElement, string, string][] = [];
let enabled = false;
let lastCodeLoc: any | undefined;

return {
highlight,
unHighlight,
};

function goToTemplate(fileName: string, range: string) {
if (!enabled) return;
lastCodeLoc = {
command: 'goToTemplate',
data: {
fileName,
range: JSON.parse(range),
},
};
parent.postMessage(lastCodeLoc, '*');
}
function highlight(node: HTMLElement, fileName: string, range: string) {
if (!enabled) return;
highlightNodes.push([node, fileName, range]);
updateOverlay();
}
function unHighlight(node: HTMLElement) {
if (!enabled) return;
highlightNodes = highlightNodes.filter(hNode => hNode[0] !== node);
updateOverlay();
}
function createOverlay() {
const overlay = document.createElement('div');
overlay.style.backgroundColor = 'rgba(65, 184, 131, 0.35)';
overlay.style.position = 'fixed';
overlay.style.zIndex = '99999999999999';
overlay.style.pointerEvents = 'none';
overlay.style.display = 'flex';
overlay.style.alignItems = 'center';
overlay.style.justifyContent = 'center';
overlay.style.borderRadius = '3px';
return overlay;
}
function createClickMask() {
const overlay = document.createElement('div');
overlay.style.position = 'fixed';
overlay.style.zIndex = '99999999999999';
overlay.style.pointerEvents = 'none';
overlay.style.display = 'flex';
overlay.style.left = '0';
overlay.style.right = '0';
overlay.style.top = '0';
overlay.style.bottom = '0';
overlay.addEventListener('mouseup', () => {
if (overlay.parentNode) {
overlay.parentNode?.removeChild(overlay)
}
});
return overlay;
}
function updateOverlay() {
if (highlightNodes.length) {
document.body.appendChild(overlay);
const highlight = highlightNodes[highlightNodes.length - 1];
const highlightNode = highlight[0];
const rect = highlightNode.getBoundingClientRect();
overlay.style.width = ~~rect.width + 'px';
overlay.style.height = ~~rect.height + 'px';
overlay.style.top = ~~rect.top + 'px';
overlay.style.left = ~~rect.left + 'px';
goToTemplate(highlight[1], highlight[2]);
}
else if (overlay.parentNode) {
overlay.parentNode.removeChild(overlay)
}
}
}

// function installPreview() {
// if (location.pathname === '/__preview') {
// const preview = defineComponent({
// setup() {
// window.addEventListener('message', event => {
// if (event.data?.command === 'updateUrl') {
// url.value = new URL(event.data.data);
// _file.value = url.value.hash.slice(1);
// }
// });
// const url = ref(new URL(location.href));
// const _file = ref(url.value.hash.slice(1));
// const file = computed(() => {
// // fix windows path for vite
// let path = _file.value.replace(/\\/g, '/');
// if (path.indexOf(':') >= 0) {
// path = path.split(':')[1];
// }
// return path;
// });
// const target = computed(() => defineAsyncComponent(() => import(file.value))); // TODO: responsive not working
// const props = computed(() => {
// const _props: Record<string, any> = {};
// url.value.searchParams.forEach((value, key) => {
// eval('_props[key] = ' + value);
// });
// return _props;
// });
// return () => h(Suspense, undefined, [
// h(target.value, props.value)
// ]);
// },
// });
// // TODO: fix preview not working if preview component is root component
// (app._component as any).setup = preview.setup;

// app.config.warnHandler = (msg) => {
// window.parent.postMessage({
// command: 'warn',
// data: msg,
// }, '*');
// console.warn(msg);
// };
// app.config.errorHandler = (msg) => {
// window.parent.postMessage({
// command: 'error',
// data: msg,
// }, '*');
// console.error(msg);
// };
// // TODO: post emit
// }
// }
});
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
24 changes: 17 additions & 7 deletions extensions/vscode-vue-language-features/package.json
Expand Up @@ -310,11 +310,6 @@
"default": true,
"description": "Show split editor icon in title area of editor."
},
"volar.icon.vite": {
"type": "boolean",
"default": true,
"description": "(Experimental) Show extra Vite features."
},
"volar.codeLens.scriptSetupTools": {
"type": "boolean",
"default": false,
Expand Down Expand Up @@ -476,7 +471,13 @@
"command": "volar.action.vite",
"title": "Experimental Features for Vite",
"category": "Volar",
"icon": "images/vite-icon.svg"
"icon": "images/vite-logo.svg"
},
{
"command": "volar.action.nuxt",
"title": "Experimental Features for Nuxt",
"category": "Volar",
"icon": "images/nuxt-logo.svg"
},
{
"command": "volar.action.tagNameCase",
Expand Down Expand Up @@ -557,6 +558,10 @@
"command": "volar.action.vite",
"when": "editorLangId == vue"
},
{
"command": "volar.action.nuxt",
"when": "editorLangId == vue"
},
{
"command": "volar.action.tagNameCase",
"when": "editorLangId == vue"
Expand Down Expand Up @@ -598,7 +603,12 @@
},
{
"command": "volar.action.vite",
"when": "editorLangId == vue && config.volar.icon.vite && volar.foundViteDir",
"when": "editorLangId == vue && volar.foundViteDir",
"group": "navigation"
},
{
"command": "volar.action.nuxt",
"when": "editorLangId == vue && volar.foundNuxtDir",
"group": "navigation"
},
{
Expand Down

0 comments on commit 4e138d4

Please sign in to comment.