mirror of
https://github.com/bendtherules/ts-transformer-visualizer.git
synced 2026-08-18 13:51:48 +00:00
lib - Add node highlighting and consume in log-identifier
This commit is contained in:
+4
-2
@@ -4,7 +4,8 @@ import {
|
|||||||
ASTVisualizer,
|
ASTVisualizer,
|
||||||
initSourceFile,
|
initSourceFile,
|
||||||
updateSourceFile,
|
updateSourceFile,
|
||||||
clearSourceFile
|
clearSourceFile,
|
||||||
|
clearHighlightedNodes
|
||||||
} from "ts-transformer-visualizer";
|
} from "ts-transformer-visualizer";
|
||||||
import * as ts from "typescript";
|
import * as ts from "typescript";
|
||||||
|
|
||||||
@@ -14,7 +15,7 @@ import { moduleMap, ModuleNames } from "./transforms";
|
|||||||
|
|
||||||
export default function App({
|
export default function App({
|
||||||
moduleName,
|
moduleName,
|
||||||
timeDelayMs = 3000
|
timeDelayMs = 1000
|
||||||
}: {
|
}: {
|
||||||
moduleName: ModuleNames;
|
moduleName: ModuleNames;
|
||||||
timeDelayMs?: number;
|
timeDelayMs?: number;
|
||||||
@@ -41,6 +42,7 @@ export default function App({
|
|||||||
// 3. Clean timeout and reset visualizer
|
// 3. Clean timeout and reset visualizer
|
||||||
clearTimeout(timeoutID);
|
clearTimeout(timeoutID);
|
||||||
clearSourceFile();
|
clearSourceFile();
|
||||||
|
clearHighlightedNodes();
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import * as ts from "typescript";
|
import * as ts from "typescript";
|
||||||
|
import { highlightNode } from "ts-transformer-visualizer";
|
||||||
|
|
||||||
import { TransformModuleExport } from "../types";
|
import { TransformModuleExport } from "../types";
|
||||||
|
|
||||||
const sourceCodeString = `\
|
const sourceCodeString = `\
|
||||||
@@ -15,6 +17,7 @@ const transformer: ts.TransformerFactory<ts.SourceFile> = context => {
|
|||||||
return sourceFile => {
|
return sourceFile => {
|
||||||
const visitor = (node: ts.Node): ts.Node => {
|
const visitor = (node: ts.Node): ts.Node => {
|
||||||
if (ts.isIdentifier(node)) {
|
if (ts.isIdentifier(node)) {
|
||||||
|
highlightNode(node);
|
||||||
console.log(node.text);
|
console.log(node.text);
|
||||||
}
|
}
|
||||||
return ts.visitEachChild(node, visitor, context);
|
return ts.visitEachChild(node, visitor, context);
|
||||||
|
|||||||
@@ -23,3 +23,9 @@
|
|||||||
}
|
}
|
||||||
.exitDone {
|
.exitDone {
|
||||||
}
|
}
|
||||||
|
.node {
|
||||||
|
padding: 0 0.5em;
|
||||||
|
}
|
||||||
|
.highlightNode {
|
||||||
|
background-color: rgba(254, 246, 2, 0.5);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,20 +1,29 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { connect } from "react-redux";
|
|
||||||
import * as ts from "typescript";
|
import * as ts from "typescript";
|
||||||
import { CSSTransition, TransitionGroup } from "react-transition-group";
|
import { CSSTransition, TransitionGroup } from "react-transition-group";
|
||||||
|
|
||||||
import { AppState } from "../../store";
|
import { useTypedSelector } from "../../store";
|
||||||
import { forEachChild, syntaxKindNameMapping, ObjectHash } from "../../utils";
|
import { forEachChild, syntaxKindNameMapping, ObjectHash } from "../../utils";
|
||||||
|
|
||||||
import styles from "./ASTOutline.css";
|
import styles from "./ASTOutline.css";
|
||||||
|
|
||||||
interface ASTOutlineProps {
|
interface ASTOutlineProps {
|
||||||
node?: ts.Node;
|
node?: ts.Node;
|
||||||
sourceFile?: ts.SourceFile;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function ASTOutline(props: ASTOutlineProps) {
|
function ASTOutline(props: ASTOutlineProps) {
|
||||||
const { node, sourceFile } = props;
|
const { node: nodeFromProps } = props;
|
||||||
|
const {
|
||||||
|
node: nodeFromRedux,
|
||||||
|
sourceFile,
|
||||||
|
highlightedNodes
|
||||||
|
} = useTypedSelector(state => ({
|
||||||
|
node: state.sourceFiles.currentSourceFile,
|
||||||
|
sourceFile: state.sourceFiles.currentSourceFile,
|
||||||
|
highlightedNodes: state.highlightedNodes.nodes
|
||||||
|
}));
|
||||||
|
const node = nodeFromProps || nodeFromRedux;
|
||||||
|
|
||||||
if (node === undefined || sourceFile === undefined) {
|
if (node === undefined || sourceFile === undefined) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -22,7 +31,13 @@ function ASTOutline(props: ASTOutlineProps) {
|
|||||||
const output = (
|
const output = (
|
||||||
<>
|
<>
|
||||||
<li>
|
<li>
|
||||||
|
<span
|
||||||
|
className={
|
||||||
|
`${styles.node} ${highlightedNodes.includes(node) ? styles.highlightNode : ""}`
|
||||||
|
}
|
||||||
|
>
|
||||||
{syntaxKindNameMapping[node.kind]}
|
{syntaxKindNameMapping[node.kind]}
|
||||||
|
</span>
|
||||||
<ul>
|
<ul>
|
||||||
<TransitionGroup>
|
<TransitionGroup>
|
||||||
{forEachChild(node).map(childNode => (
|
{forEachChild(node).map(childNode => (
|
||||||
@@ -31,7 +46,7 @@ function ASTOutline(props: ASTOutlineProps) {
|
|||||||
timeout={1000}
|
timeout={1000}
|
||||||
classNames={styles}
|
classNames={styles}
|
||||||
>
|
>
|
||||||
<ASTOutlineConnected node={childNode} />
|
<ASTOutline node={childNode} />
|
||||||
</CSSTransition>
|
</CSSTransition>
|
||||||
))}
|
))}
|
||||||
</TransitionGroup>
|
</TransitionGroup>
|
||||||
@@ -51,28 +66,4 @@ function ASTOutline(props: ASTOutlineProps) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type ASTOutlineStateProps = ASTOutlineProps;
|
export default ASTOutline;
|
||||||
|
|
||||||
const mapStateToProps = (state: AppState) => ({
|
|
||||||
node: state.sourceFiles.currentSourceFile,
|
|
||||||
sourceFile: state.sourceFiles.currentSourceFile
|
|
||||||
});
|
|
||||||
// currentSourceFile from ownProps should take preceedence
|
|
||||||
const mergeProps = (
|
|
||||||
stateProps: ASTOutlineStateProps,
|
|
||||||
_dispatchProps: never,
|
|
||||||
ownProps: ASTOutlineProps
|
|
||||||
) => {
|
|
||||||
return {
|
|
||||||
...stateProps,
|
|
||||||
...ownProps
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export { ASTOutline as ASTOutlineUnconnected, ASTOutlineProps };
|
|
||||||
const ASTOutlineConnected = connect(
|
|
||||||
mapStateToProps,
|
|
||||||
null,
|
|
||||||
mergeProps
|
|
||||||
)(ASTOutline);
|
|
||||||
export default ASTOutlineConnected;
|
|
||||||
|
|||||||
@@ -1,7 +1,3 @@
|
|||||||
import ASTOutline, {
|
import ASTOutline from "./ASTOutline";
|
||||||
ASTOutlineUnconnected,
|
|
||||||
ASTOutlineProps
|
|
||||||
} from "./ASTOutline";
|
|
||||||
|
|
||||||
export { ASTOutlineUnconnected, ASTOutlineProps };
|
|
||||||
export default ASTOutline;
|
export default ASTOutline;
|
||||||
|
|||||||
+24
-8
@@ -10,7 +10,9 @@ import configureStore from "./store";
|
|||||||
import {
|
import {
|
||||||
initSourceFile,
|
initSourceFile,
|
||||||
updateSourceFile,
|
updateSourceFile,
|
||||||
clearSourceFile
|
clearSourceFile,
|
||||||
|
highlightNode,
|
||||||
|
clearHighlightedNodes
|
||||||
} from "./store/sourceFiles/actions";
|
} from "./store/sourceFiles/actions";
|
||||||
|
|
||||||
import styles from "./styles.css";
|
import styles from "./styles.css";
|
||||||
@@ -27,19 +29,23 @@ export function ASTVisualizer() {
|
|||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
<Row>
|
<Row>
|
||||||
<Col xs={12} md={6} className={styles.hideOverflow}>
|
<Col xs={12} className={styles.hideOverflow}>
|
||||||
<Row>
|
<Row>
|
||||||
<h2 className={styles.titleLight}>AST Inline Diff</h2>
|
<h2 className={styles.titleLight}>AST Inline Diff</h2>
|
||||||
</Row>
|
</Row>
|
||||||
<ASTOutline />
|
<ASTOutline />
|
||||||
</Col>
|
</Col>
|
||||||
<Col xs={12} md={6}>
|
<Col xs={12}>
|
||||||
<Row>
|
<Row>
|
||||||
<h2 className={styles.titleLight}>Code output Diff</h2>
|
<h2 className={styles.titleLight}>Code output Diff</h2>
|
||||||
</Row>
|
</Row>
|
||||||
<Row>
|
<Row>
|
||||||
<Col xs={6} className={styles.titleLight}>Input</Col>
|
<Col xs={6} className={styles.titleLight}>
|
||||||
<Col xs={6} className={styles.titleLight}>Output</Col>
|
Input
|
||||||
|
</Col>
|
||||||
|
<Col xs={6} className={styles.titleLight}>
|
||||||
|
Output
|
||||||
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
<CodeOutputDiff />
|
<CodeOutputDiff />
|
||||||
</Col>
|
</Col>
|
||||||
@@ -52,14 +58,24 @@ export function ASTVisualizer() {
|
|||||||
const {
|
const {
|
||||||
initSourceFile: initSourceFileConnected,
|
initSourceFile: initSourceFileConnected,
|
||||||
updateSourceFile: updateSourceFileConnected,
|
updateSourceFile: updateSourceFileConnected,
|
||||||
clearSourceFile: clearSourceFileConnected
|
clearSourceFile: clearSourceFileConnected,
|
||||||
|
highlightNode: highlightNodeConnected,
|
||||||
|
clearHighlightedNodes: clearHighlightedNodesConnected
|
||||||
} = bindActionCreators(
|
} = bindActionCreators(
|
||||||
{ initSourceFile, updateSourceFile, clearSourceFile },
|
{
|
||||||
|
initSourceFile,
|
||||||
|
updateSourceFile,
|
||||||
|
clearSourceFile,
|
||||||
|
highlightNode,
|
||||||
|
clearHighlightedNodes
|
||||||
|
},
|
||||||
store.dispatch
|
store.dispatch
|
||||||
);
|
);
|
||||||
|
|
||||||
export {
|
export {
|
||||||
initSourceFileConnected as initSourceFile,
|
initSourceFileConnected as initSourceFile,
|
||||||
updateSourceFileConnected as updateSourceFile,
|
updateSourceFileConnected as updateSourceFile,
|
||||||
clearSourceFileConnected as clearSourceFile
|
clearSourceFileConnected as clearSourceFile,
|
||||||
|
highlightNodeConnected as highlightNode,
|
||||||
|
clearHighlightedNodesConnected as clearHighlightedNodes
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,12 +4,17 @@ import {
|
|||||||
applyMiddleware,
|
applyMiddleware,
|
||||||
Middleware
|
Middleware
|
||||||
} from "redux";
|
} from "redux";
|
||||||
|
import { useSelector, TypedUseSelectorHook } from "react-redux";
|
||||||
import { composeWithDevTools } from "redux-devtools-extension";
|
import { composeWithDevTools } from "redux-devtools-extension";
|
||||||
|
|
||||||
import { sourceFilesReducer } from "./sourceFiles/reducer";
|
import {
|
||||||
|
sourceFilesReducer,
|
||||||
|
highlightedNodesReducer
|
||||||
|
} from "./sourceFiles/reducer";
|
||||||
|
|
||||||
const rootReducer = combineReducers({
|
const rootReducer = combineReducers({
|
||||||
sourceFiles: sourceFilesReducer
|
sourceFiles: sourceFilesReducer,
|
||||||
|
highlightedNodes: highlightedNodesReducer
|
||||||
});
|
});
|
||||||
|
|
||||||
export type AppState = ReturnType<typeof rootReducer>;
|
export type AppState = ReturnType<typeof rootReducer>;
|
||||||
@@ -25,3 +30,5 @@ export default function configureStore() {
|
|||||||
|
|
||||||
return store;
|
return store;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const useTypedSelector: TypedUseSelectorHook<AppState> = useSelector;
|
||||||
|
|||||||
@@ -1,22 +1,50 @@
|
|||||||
import * as ts from "typescript";
|
import * as ts from "typescript";
|
||||||
import { INIT_SOURCEFILE, UPDATE_SOURCEFILE, CLEAR_SOURCEFILE } from "./types";
|
import {
|
||||||
|
INIT_SOURCEFILE,
|
||||||
|
UPDATE_SOURCEFILE,
|
||||||
|
CLEAR_SOURCEFILE,
|
||||||
|
HIGHLIGHT_NODE,
|
||||||
|
CLEAR_HIGHLIGHTED_NODES,
|
||||||
|
InitSourceFileAction,
|
||||||
|
UpdateSourceFileAction,
|
||||||
|
ClearSourceFileAction,
|
||||||
|
HighlightNodeAction,
|
||||||
|
ClearHighlightedNodesAction
|
||||||
|
} from "./types";
|
||||||
|
|
||||||
export function initSourceFile(sourceFile: ts.SourceFile) {
|
export function initSourceFile(
|
||||||
|
sourceFile: ts.SourceFile
|
||||||
|
): InitSourceFileAction {
|
||||||
return {
|
return {
|
||||||
type: INIT_SOURCEFILE,
|
type: INIT_SOURCEFILE,
|
||||||
payload: { sourceFile }
|
payload: { sourceFile }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function updateSourceFile(sourceFile: ts.SourceFile) {
|
export function updateSourceFile(
|
||||||
|
sourceFile: ts.SourceFile
|
||||||
|
): UpdateSourceFileAction {
|
||||||
return {
|
return {
|
||||||
type: UPDATE_SOURCEFILE,
|
type: UPDATE_SOURCEFILE,
|
||||||
payload: { sourceFile }
|
payload: { sourceFile }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function clearSourceFile() {
|
export function clearSourceFile(): ClearSourceFileAction {
|
||||||
return {
|
return {
|
||||||
type: CLEAR_SOURCEFILE,
|
type: CLEAR_SOURCEFILE
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function highlightNode(node: ts.Node): HighlightNodeAction {
|
||||||
|
return {
|
||||||
|
type: HIGHLIGHT_NODE,
|
||||||
|
payload: { node }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function clearHighlightedNodes(): ClearHighlightedNodesAction {
|
||||||
|
return {
|
||||||
|
type: CLEAR_HIGHLIGHTED_NODES
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,17 +2,24 @@ import {
|
|||||||
INIT_SOURCEFILE,
|
INIT_SOURCEFILE,
|
||||||
UPDATE_SOURCEFILE,
|
UPDATE_SOURCEFILE,
|
||||||
CLEAR_SOURCEFILE,
|
CLEAR_SOURCEFILE,
|
||||||
|
HIGHLIGHT_NODE,
|
||||||
|
CLEAR_HIGHLIGHTED_NODES,
|
||||||
SourceFilesState,
|
SourceFilesState,
|
||||||
SourceFilesActionTypes
|
HighlightedNodesState,
|
||||||
|
SourceFilesActionTypes,
|
||||||
|
HighlightNodeActionTypes
|
||||||
} from "./types";
|
} from "./types";
|
||||||
|
|
||||||
const initialState: SourceFilesState = {
|
const initialSourceFileState: SourceFilesState = {
|
||||||
inititalSourceFile: undefined,
|
inititalSourceFile: undefined,
|
||||||
currentSourceFile: undefined
|
currentSourceFile: undefined
|
||||||
};
|
};
|
||||||
|
const initialHighlightedNodesState: HighlightedNodesState = {
|
||||||
|
nodes: []
|
||||||
|
};
|
||||||
|
|
||||||
export function sourceFilesReducer(
|
export function sourceFilesReducer(
|
||||||
state = initialState,
|
state = initialSourceFileState,
|
||||||
action: SourceFilesActionTypes
|
action: SourceFilesActionTypes
|
||||||
): SourceFilesState {
|
): SourceFilesState {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
@@ -28,7 +35,24 @@ export function sourceFilesReducer(
|
|||||||
currentSourceFile: action.payload.sourceFile
|
currentSourceFile: action.payload.sourceFile
|
||||||
};
|
};
|
||||||
case CLEAR_SOURCEFILE:
|
case CLEAR_SOURCEFILE:
|
||||||
return initialState;
|
return initialSourceFileState;
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function highlightedNodesReducer(
|
||||||
|
state = initialHighlightedNodesState,
|
||||||
|
action: HighlightNodeActionTypes
|
||||||
|
): HighlightedNodesState {
|
||||||
|
switch (action.type) {
|
||||||
|
case HIGHLIGHT_NODE:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
nodes: [...state.nodes, action.payload.node]
|
||||||
|
};
|
||||||
|
case CLEAR_HIGHLIGHTED_NODES:
|
||||||
|
return initialHighlightedNodesState;
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,26 +6,46 @@ export interface SourceFilesState {
|
|||||||
currentSourceFile?: ts.SourceFile;
|
currentSourceFile?: ts.SourceFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// slice for highlighted nodes
|
||||||
|
export interface HighlightedNodesState {
|
||||||
|
nodes: ts.Node[];
|
||||||
|
}
|
||||||
|
|
||||||
// Describing the different ACTION NAMES available
|
// Describing the different ACTION NAMES available
|
||||||
export const INIT_SOURCEFILE = "INIT_SOURCEFILE";
|
export const INIT_SOURCEFILE = "INIT_SOURCEFILE";
|
||||||
export const UPDATE_SOURCEFILE = "UPDATE_SOURCEFILE";
|
export const UPDATE_SOURCEFILE = "UPDATE_SOURCEFILE";
|
||||||
export const CLEAR_SOURCEFILE = "CLEAR_SOURCEFILE";
|
export const CLEAR_SOURCEFILE = "CLEAR_SOURCEFILE";
|
||||||
|
export const HIGHLIGHT_NODE = "HIGHLIGHT_NODE";
|
||||||
|
export const CLEAR_HIGHLIGHTED_NODES = "CLEAR_HIGHLIGHTED_NODES";
|
||||||
|
|
||||||
interface InitSourceFileAction {
|
export interface InitSourceFileAction {
|
||||||
type: typeof INIT_SOURCEFILE;
|
type: typeof INIT_SOURCEFILE;
|
||||||
payload: { sourceFile: ts.SourceFile };
|
payload: { sourceFile: ts.SourceFile };
|
||||||
}
|
}
|
||||||
|
|
||||||
interface UpdateSourceFileAction {
|
export interface UpdateSourceFileAction {
|
||||||
type: typeof UPDATE_SOURCEFILE;
|
type: typeof UPDATE_SOURCEFILE;
|
||||||
payload: { sourceFile: ts.SourceFile };
|
payload: { sourceFile: ts.SourceFile };
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ClearSourceFileAction {
|
export interface ClearSourceFileAction {
|
||||||
type: typeof CLEAR_SOURCEFILE;
|
type: typeof CLEAR_SOURCEFILE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface HighlightNodeAction {
|
||||||
|
type: typeof HIGHLIGHT_NODE;
|
||||||
|
payload: { node: ts.Node };
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ClearHighlightedNodesAction {
|
||||||
|
type: typeof CLEAR_HIGHLIGHTED_NODES;
|
||||||
|
}
|
||||||
|
|
||||||
export type SourceFilesActionTypes =
|
export type SourceFilesActionTypes =
|
||||||
| InitSourceFileAction
|
| InitSourceFileAction
|
||||||
| UpdateSourceFileAction
|
| UpdateSourceFileAction
|
||||||
| ClearSourceFileAction;
|
| ClearSourceFileAction;
|
||||||
|
|
||||||
|
export type HighlightNodeActionTypes =
|
||||||
|
| HighlightNodeAction
|
||||||
|
| ClearHighlightedNodesAction;
|
||||||
|
|||||||
Reference in New Issue
Block a user