chore: use source-ref

pull/49/head
moonrailgun 3 years ago
parent 2371c90f07
commit 27fe626000

@ -1 +0,0 @@
## source-ref for webpack loader

@ -1,37 +0,0 @@
{
"name": "rollup-plugin-source-ref",
"version": "1.0.0",
"description": "",
"main": "lib/index.js",
"files": [
"lib"
],
"scripts": {
"build": "tsc",
"prepare": "tsc"
},
"keywords": [
"sourcecode",
"pointer",
"webpack"
],
"author": "moonrailgun",
"license": "MIT",
"devDependencies": {
"@types/babel__generator": "^7.6.4",
"@types/babel__traverse": "^7.17.1",
"@types/node": "^15.12.5",
"@types/webpack": "^5.28.0",
"rollup": "^2.75.0",
"ts-node": "^10.0.0",
"typescript": "^4.5.2",
"webpack": "^5.72.0",
"webpack-test-utils": "^1.1.0"
},
"dependencies": {
"@babel/generator": "^7.17.7",
"@babel/parser": "^7.17.7",
"@babel/traverse": "^7.17.3",
"@babel/types": "^7.17.10"
}
}

@ -1,73 +0,0 @@
import type { Plugin } from 'rollup';
import { parse } from '@babel/parser';
import traverse from '@babel/traverse';
import generate from '@babel/generator';
import {
isJSXIdentifier,
isJSXMemberExpression,
jsxAttribute,
jsxIdentifier,
stringLiteral,
} from '@babel/types';
const TRACE_ID = 'data-source';
export default function sourceRef(): Plugin {
return {
name: 'source-ref',
transform(code, id) {
const filepath = id;
const ast = parse(code, {
sourceType: 'module',
plugins: ['jsx', 'typescript'],
});
traverse(ast, {
JSXOpeningElement(path) {
const location = path.node.loc;
if (!location) {
return;
}
if (Array.isArray(location)) {
return;
}
const name = path.node.name;
if (isJSXIdentifier(name) && name.name === 'Fragment') {
return;
}
if (
isJSXMemberExpression(name) &&
name.property.name === 'Fragment'
) {
return;
}
const line = location.start.line;
const col = location.start.column;
const attrs = path.node.attributes;
for (let i = 0; i < attrs.length; i++) {
const attr = attrs[i];
if (attr.type === 'JSXAttribute' && attr.name.name === TRACE_ID) {
// existed
return;
}
}
const traceId = `${filepath}:${line}:${col}`;
attrs.push(
jsxAttribute(jsxIdentifier(TRACE_ID), stringLiteral(traceId))
);
},
});
const res = generate(ast);
return { code: res.code, map: res.map };
},
};
}

@ -1,14 +0,0 @@
{
"compilerOptions": {
"outDir": "lib",
"module": "commonjs",
"target": "ES5",
"lib": ["ESNext"],
"declaration": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"esModuleInterop": true,
"skipLibCheck": true
},
"include": ["src"]
}

@ -1 +0,0 @@
## source-ref for webpack loader

@ -1,37 +0,0 @@
{
"name": "source-ref-loader",
"version": "1.0.0",
"description": "",
"main": "lib/index.js",
"files": [
"lib"
],
"scripts": {
"build": "tsc",
"prepare": "tsc",
"test": "ts-node ./test/index.ts"
},
"keywords": [
"sourcecode",
"pointer",
"webpack"
],
"author": "moonrailgun",
"license": "MIT",
"devDependencies": {
"@types/babel__generator": "^7.6.4",
"@types/babel__traverse": "^7.17.1",
"@types/node": "^15.12.5",
"@types/webpack": "^5.28.0",
"ts-node": "^10.0.0",
"typescript": "^4.5.2",
"webpack": "^5.72.0",
"webpack-test-utils": "^1.1.0"
},
"dependencies": {
"@babel/generator": "^7.17.7",
"@babel/parser": "^7.17.7",
"@babel/traverse": "^7.17.3",
"@babel/types": "^7.17.10"
}
}

@ -1,77 +0,0 @@
import type { LoaderContext } from 'webpack';
import { parse } from '@babel/parser';
import traverse from '@babel/traverse';
import generate from '@babel/generator';
import {
isJSXIdentifier,
isJSXMemberExpression,
jsxAttribute,
jsxIdentifier,
stringLiteral,
} from '@babel/types';
const TRACE_ID = 'data-source';
async function loader(this: LoaderContext<any>, source: string): Promise<void> {
const done = this.async();
const { available } = this.getOptions();
if (!available) {
// skip if not
done(null, source);
return;
}
const ast = parse(source, {
sourceType: 'module',
plugins: ['jsx', 'typescript'],
});
const filepath = this.resourcePath;
if (filepath.includes('node_modules')) {
done(null, source);
return;
}
traverse(ast, {
JSXOpeningElement(path) {
const location = path.node.loc;
if (!location) {
return;
}
if (Array.isArray(location)) {
return;
}
const name = path.node.name;
if (isJSXIdentifier(name) && name.name === 'Fragment') {
return;
}
if (isJSXMemberExpression(name) && name.property.name === 'Fragment') {
return;
}
const line = location.start.line;
const col = location.start.column;
const attrs = path.node.attributes;
for (let i = 0; i < attrs.length; i++) {
const attr = attrs[i];
if (attr.type === 'JSXAttribute' && attr.name.name === TRACE_ID) {
// existed
return;
}
}
const traceId = `${filepath}:${line}:${col}`;
attrs.push(jsxAttribute(jsxIdentifier(TRACE_ID), stringLiteral(traceId)));
},
});
const code = generate(ast).code;
done(null, code);
}
export default loader;

@ -1,20 +0,0 @@
export const tsx = {
'/src/index.js': `
import Foo, { HelloWorld } from './foo.tsx'
export default [
HelloWorld,
(new Foo()).render(),
];
`,
'/src/foo.tsx': `
export const HelloWorld = <><div>hello world</div></>;
export const HelloWorld2 = <React.Fragment><div>hello world</div></React.Fragment>;
export const HelloWorld3 = <Fragment><div>hello world</div></Fragment>;
export default class Foo {
render() {
return <div className="class-name">content</div>
}
}
`,
};

@ -1,17 +0,0 @@
import { build } from 'webpack-test-utils';
import * as fixtures from './fixtures';
import { configureLoader } from './utils';
async function test() {
const built = await build(fixtures.tsx, (config) => {
configureLoader(config);
console.log('configureLoader(config);', config.module.rules);
});
console.log('usage:', built.stats.endTime - built.stats.startTime, 'ms');
console.log('errors:', built.stats.compilation.errors.length);
// console.log(built.stats.compilation.errors);
}
test();

@ -1,18 +0,0 @@
import type { Configuration } from 'webpack';
import type { DefaultWebpackConfig } from 'webpack-test-utils';
const loaderPath = require.resolve('../src/index.ts');
export function configureLoader(config: DefaultWebpackConfig & Configuration) {
config.resolveLoader.alias = {
'source-ref-loader': loaderPath,
};
config.module.rules.push({
test: /\.tsx$/,
loader: 'source-ref-loader',
options: {
available: true,
},
});
}

@ -1,16 +0,0 @@
{
"compilerOptions": {
"outDir": "lib",
"module": "commonjs",
"target": "ES2018",
"lib": ["ES2018"],
"declaration": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"esModuleInterop": true,
"skipLibCheck": true
},
"include": ["src"]
}

@ -1 +0,0 @@
declare module 'source-ref-open-vscode' {}

@ -1,223 +0,0 @@
(function (win, doc) {
const sourceMap = {};
const sourceMapReverse = {};
let cursor = 0;
let timer = null;
function openVscode(node) {
let path = null;
if (node.dataset.sid) {
path = sidToURI(node.dataset.sid);
}
if (node.dataset.source) {
path = 'vscode://file/' + node.dataset.source;
}
if (!path) {
return console.warn('Not found data-source');
}
win.location.href = path;
}
function sourceToId(node) {
if (!node.dataset.source) return;
const source = node.dataset.source;
const splits = source.split(':');
const column = splits.pop();
const row = splits.pop();
const file = splits.join(':');
if (!sourceMap[file]) {
cursor++;
sourceMap[file] = cursor;
sourceMapReverse[cursor] = file;
}
const id = sourceMap[file];
node.removeAttribute('data-source');
node.setAttribute('data-sid', `${id}:${row}:${column}`);
}
function sidToURI(sid) {
const [id, row, column] = sid.split(':');
const path =
'vscode://file/' + sourceMapReverse[id] + ':' + row + ':' + column;
return path;
}
class Selector {
constructor(node) {
this.sids = [];
this.containerId = '__source-ref-panel';
this.getAncestorSids = (node) => {
const sids = [];
let cur = node;
while (cur !== doc.body) {
if (cur.dataset.sid) {
sids.push(cur.dataset.sid);
}
cur = cur.parentElement;
}
return sids;
};
this.focusBlock = null;
this.setFocusBlock = (target) => {
if (target === null) {
// clear if target is null
if (this.focusBlock) {
doc.body.removeChild(this.focusBlock);
this.focusBlock = null;
}
return;
}
if (!this.focusBlock) {
this.focusBlock = doc.createElement('div');
this.focusBlock.className = '__source-ref-mask';
this.focusBlock.style.position = 'absolute';
this.focusBlock.style.backgroundColor = 'rgba(134, 185, 242, 0.5)';
doc.body.appendChild(this.focusBlock);
}
const rect = target.getBoundingClientRect();
this.focusBlock.style.height = rect.height + 'px';
this.focusBlock.style.width = rect.width + 'px';
this.focusBlock.style.left = rect.x + 'px';
this.focusBlock.style.top = rect.y + 'px';
};
this.getContainer = () => {
const container = doc.getElementById(this.containerId);
if (!container) {
const div = doc.createElement('div');
div.id = this.containerId;
doc.body.appendChild(div);
// Add dom red border on hover
div.addEventListener('mouseover', (e) => {
const node = e.target;
if (node.dataset.tid) {
const target = doc.querySelector(
`[data-sid="${node.dataset.tid}"]`
);
if (target) {
target.classList.add('__source-ref-selected');
this.setFocusBlock(target);
}
}
});
// Remove dom red border when leave
div.addEventListener('mouseout', (e) => {
const node = e.target;
if (node.dataset.tid) {
const target = doc.querySelector(
`[data-sid="${node.dataset.tid}"]`
);
if (target) {
target.classList.remove('__source-ref-selected');
}
}
});
const close = () => {
this.setFocusBlock(null);
doc.body.removeChild(div);
};
// click event
div.addEventListener('click', (e) => {
const node = e.target;
const command = node.dataset.command;
switch (command) {
case 'close': {
e.stopPropagation();
close();
return;
}
default:
console.warn('Unknown command', command);
}
});
// keyboard event
function escKeyHandler(e) {
if (e.key === 'Escape') {
e.stopPropagation();
close();
doc.removeEventListener('keydown', escKeyHandler);
}
}
doc.addEventListener('keydown', escKeyHandler);
return div;
}
return container;
};
this.renderHTML = () => {
const html = `
<div style="
position: fixed;
background: white;
bottom: 0;
left: 0;
z-index: 9999;
opacity: 0.6;
border-radius: 0 10px 0 0;
">
<div style="cursor:pointer;margin:10px;text-align:right;font-size:18px;" data-command="close">X</div>
${this.sids
.map((sid) => {
const uri = sidToURI(sid);
// 这里加了一个左向省略,暂时没用上,先放着
return `<a href="${uri}" style="
display: block;
margin: 10px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
direction: rtl;
text-align: left;
" data-tid="${sid}">source-ref: ${uri}</a>`;
})
.join('')}
</div>
`;
const container = this.getContainer();
container.innerHTML = html;
};
this.sids = this.getAncestorSids(node);
}
}
function init() {
win.vscode = (node = win.$0) => {
openVscode(node);
};
doc.body.addEventListener(
'click',
(e) => {
if (e.altKey) {
e.preventDefault();
e.stopPropagation();
const selector = new Selector(e.target);
selector.renderHTML();
}
},
true
);
const mo = new MutationObserver(() => {
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(() => {
// recal sid
doc
.querySelectorAll('[data-source]')
.forEach((node) => sourceToId(node));
}, 500);
});
mo.observe(doc.body, {
attributes: true,
childList: true,
subtree: true,
});
}
init();
})(window, document);

@ -1,13 +0,0 @@
{
"name": "source-ref-open-vscode",
"version": "1.0.0",
"description": "",
"main": "index.js",
"types": "index.d.ts",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "moonrailgun",
"license": "MIT"
}

@ -350,10 +350,10 @@ importers:
rimraf: ^3.0.2
rollup-plugin-copy: ^3.4.0
rollup-plugin-replace: ^2.2.0
rollup-plugin-source-ref: workspace:^1.0.0
rollup-plugin-source-ref: ^1.0.0
socket.io-client: ^4.1.2
source-ref-loader: workspace:^1.0.0
source-ref-open-vscode: workspace:^1.0.0
source-ref-loader: ^1.0.0
source-ref-runtime: ^1.0.0
style-loader: ^3.0.0
tailchat-design: workspace:^1.0.0
tailchat-plugin-declaration-generator: workspace:^1.0.0
@ -405,7 +405,7 @@ importers:
react-virtualized-auto-sizer: 1.0.6_sfoxds7t5ydpegc3knd667wn6m
react-virtuoso: 2.11.0_sfoxds7t5ydpegc3knd667wn6m
socket.io-client: 4.4.0
source-ref-open-vscode: link:../packages/source-ref-open-vscode
source-ref-runtime: 1.0.0
tailchat-design: link:../packages/design
tailchat-shared: link:../shared
tailwindcss: 2.2.19_hqu7j45oxtlo2g5y3qitzppg3y
@ -458,8 +458,8 @@ importers:
rimraf: 3.0.2
rollup-plugin-copy: 3.4.0
rollup-plugin-replace: 2.2.0
rollup-plugin-source-ref: link:../packages/rollup-plugin-source-ref
source-ref-loader: link:../packages/source-ref-loader
rollup-plugin-source-ref: 1.0.0
source-ref-loader: 1.0.0
style-loader: 3.3.1_webpack@5.73.0
tailchat-plugin-declaration-generator: link:../packages/plugin-declaration-generator
ts-jest: 27.1.4_ibhx3ehxrt2kgmkik4bkzmyeei
@ -15864,6 +15864,14 @@ packages:
rollup-pluginutils: 2.8.2
dev: true
/rollup-plugin-source-ref/1.0.0:
resolution: {integrity: sha512-lJsEb3Z750Kocl1dc7sl4X+H29JTA1WQkf2H/4lpPI92akWpVWnq3u0hGD/2TKs1S0cz9F5BVKN2fn/aQXh+mw==}
dependencies:
source-ref-core: 1.0.1
transitivePeerDependencies:
- supports-color
dev: true
/rollup-plugin-styles/3.14.1_rollup@2.72.1:
resolution: {integrity: sha512-0JodP26O3WZ8320X3sBn5S2SOPv9Al2tLyOmLco+H2UqLjbmycM9KWGypLjcDuIEWwa0oLYiXpViMmO2yyeqIA==}
engines: {node: '>=10'}
@ -16463,6 +16471,29 @@ packages:
whatwg-url: 7.1.0
dev: true
/source-ref-core/1.0.1:
resolution: {integrity: sha512-MKflr0a0XKfpPSzLfLZU7RZm99yqpdhsdy+qFxPjbCdjnBHskeRnn6QqDGi7XhBsB3jhYhdkHI7JP5dg+nvjbA==}
dependencies:
'@babel/generator': 7.17.10
'@babel/parser': 7.17.10
'@babel/traverse': 7.17.10
'@babel/types': 7.17.10
transitivePeerDependencies:
- supports-color
dev: true
/source-ref-loader/1.0.0:
resolution: {integrity: sha512-sdZq8Z1NBwVLKJWb4a6ycd3+jLqWLBAy8l2OfdvZ0aVku0d6lCpRKfz1NwmtnPvz8kj7Cok1QIhAnutCLGKcbw==}
dependencies:
source-ref-core: 1.0.1
transitivePeerDependencies:
- supports-color
dev: true
/source-ref-runtime/1.0.0:
resolution: {integrity: sha512-l0UyA7K7+uMjQnTXYL4fnaa98HamyUy+AyfkqQX2Pr4xynH/d8JczCaVfsJsg88+/Ln/1yo69qGih7TmyMqzZw==}
dev: false
/sourcemap-codec/1.4.8:
resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==}

@ -55,7 +55,7 @@
"react-virtualized-auto-sizer": "^1.0.6",
"react-virtuoso": "^2.8.3",
"socket.io-client": "^4.1.2",
"source-ref-open-vscode": "workspace:^1.0.0",
"source-ref-runtime": "^1.0.0",
"tailchat-design": "workspace:^1.0.0",
"tailchat-shared": "*",
"tailwindcss": "^2.2.4",
@ -109,8 +109,8 @@
"rimraf": "^3.0.2",
"rollup-plugin-copy": "^3.4.0",
"rollup-plugin-replace": "^2.2.0",
"rollup-plugin-source-ref": "workspace:^1.0.0",
"source-ref-loader": "workspace:^1.0.0",
"rollup-plugin-source-ref": "^1.0.0",
"source-ref-loader": "^1.0.0",
"style-loader": "^3.0.0",
"tailchat-plugin-declaration-generator": "workspace:^1.0.0",
"ts-jest": "^27.1.2",

@ -22,7 +22,7 @@ import { getUserJWT } from './utils/jwt-helper';
import _get from 'lodash/get';
if (isDevelopment) {
import('source-ref-open-vscode');
import('source-ref-runtime').then(({ start }) => start());
}
const webStorage = buildStorage(window.localStorage);

Loading…
Cancel
Save