lib - Add node highlighting and consume in log-identifier

This commit is contained in:
2020-01-29 13:42:38 +05:30
parent 3feecc6750
commit a32cd478ac
10 changed files with 153 additions and 60 deletions
+4 -2
View File
@@ -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);
}
+22 -31
View File
@@ -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>
{syntaxKindNameMapping[node.kind]} <span
className={
`${styles.node} ${highlightedNodes.includes(node) ? styles.highlightNode : ""}`
}
>
{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 -5
View File
@@ -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
View File
@@ -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
}; };
+9 -2
View File
@@ -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;
+33 -5
View File
@@ -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
}; };
} }
+28 -4
View File
@@ -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;
} }
+23 -3
View File
@@ -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;