Skip to content

Commit

Permalink
Merge pull request #241 from RaoHai/fix/passing-errorRefs-in-props
Browse files Browse the repository at this point in the history
fix: passing errorRefs in props
  • Loading branch information
RaoHai authored Sep 8, 2020
2 parents 4d24c66 + e4c8490 commit dcb9e21
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 60 deletions.
17 changes: 12 additions & 5 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-ansi",
"version": "2.0.1",
"version": "2.1.0",
"description": "",
"author": "RaoHai",
"license": "MIT",
Expand Down Expand Up @@ -29,7 +29,8 @@
},
"dependencies": {
"anser": "^1.4.8",
"escape-carriage": "^1.3.0"
"escape-carriage": "^1.3.0",
"immer": "^7.0.8"
},
"peerDependencies": {
"prop-types": "^15.5.4",
Expand Down
64 changes: 34 additions & 30 deletions src/component/RawLogger.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React, { useState, ReactNode, useMemo, useEffect, useContext } from 'react';
import React, { useState, ReactNode, useEffect, useContext } from 'react';
import Anser, { AnserJsonEntry } from 'anser';
import { escapeCarriageReturn } from 'escape-carriage';
import { Partical } from '../matcher';
import { ErrorMatcher } from '../errorMatcher';
import { ErrorMatcher, ErrorMatcherPattern } from '../errorMatcher';

import styles from '../style/log.module.less';
import { ErrorContext } from '../model/ErrorContext';
Expand Down Expand Up @@ -126,11 +126,33 @@ export function RawLogger({
useClasses?: boolean;
linkify?: boolean;
}) {
const { setErrorRefs } = useContext(ErrorContext);
const lineProps = { useClasses, linkify, errorMatcher };
const [fold, setFold] = useState(partical.fold);

const lines = React.useMemo(() => {
return partical.content.split('\n').map((line, index) => (
<Line {...lineProps} line={line} index={index} />
const lines = partical.content.split('\n').map(line => {
return ansiToJSON(line).reduce((prev, bundle, index) => {
const content = convertBundleIntoReact(useClasses, linkify, bundle, index);
const errors = errorMatcher.match(bundle);
return {
content: prev.content.concat([content]),
errors: prev.errors.concat(errors),
}
}, {
content: [] as any,
errors: [] as ErrorMatcher['patterns'],
});
});

return lines.map((line, index) => (
<Line
{...lineProps}
line={line.content}
errors={line.errors}
index={index}
saveRef={setErrorRefs}
/>
));
}, [partical, styles, useClasses, linkify, errorMatcher]);

Expand All @@ -156,46 +178,28 @@ export function RawLogger({

export function Line({
line,
useClasses,
linkify,
errorMatcher,
errors,
index,
saveRef,
}: {
line: string;
errorMatcher: ErrorMatcher;
useClasses: boolean;
linkify: boolean;
errors: ErrorMatcher['patterns'],
index: number,
saveRef: (errors: ErrorMatcherPattern[], ref: HTMLDivElement) => void;
}) {
const { setErrorRefs } = useContext(ErrorContext);
const { errors, content } = useMemo(() => {
return ansiToJSON(line).reduce((prev, bundle, index) => {
const content = convertBundleIntoReact(useClasses, linkify, bundle, index);
const errors = errorMatcher.match(bundle);
return {
content: prev.content.concat([content]),
errors: prev.errors.concat(errors),
}
}, {
content: [] as any,
errors: [] as ErrorMatcher['patterns'],
});
}, [line]);

const ref = React.createRef<HTMLDivElement>();

useEffect(() => {
if (errors.length && ref.current) {
if (errors.length && setErrorRefs) {
setErrorRefs(errors, ref.current);
}
if (errors.length && ref.current && saveRef) {
saveRef(errors, ref.current);
}
}, [ref, errors, setErrorRefs]);
}, [ref.current, errors]);

return (
<div className={`${styles.logLine} ${errors.length ? styles.error : ''}`} key={index} ref={ref}>
<a className={styles.lineNo} />
{content}
{line}
</div>
);
}
63 changes: 42 additions & 21 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,20 @@
* An foldable ansi logger for react
* Inspired by ansi-to-react: https://github.com/nteract/nteract/blob/master/packages/ansi-to-react
*/
import React, { useRef, useEffect, useState } from 'react';
import React, { useRef, useEffect, useState, useCallback } from 'react';
import produce, { enableMapSet } from 'immer';
import { _ } from './utils/i18n';
import { Spliter, defaultMatchers } from './model/Spliter';

import { Matcher } from './matcher';
import { ErrorMatcher, defaultErrorMatchers, ErrorMatcherPatterns } from './errorMatcher';
import { ErrorMatcher, defaultErrorMatchers, ErrorMatcherPatterns, ErrorMatcherPattern } from './errorMatcher';
import { LogContent } from './component/LogContent';
import { ErrorContext, errorRefs } from './model/ErrorContext';

import styles from './style/log.module.less';

enableMapSet();

const MemorizedLogContent = React.memo(LogContent);

export { Matcher, ErrorContext, errorRefs };
Expand All @@ -26,13 +29,21 @@ export interface FoldableLoggerProps {
autoScroll?: boolean;
showHeader?: boolean;
linkify?: boolean;
children: ({
hasError,
errors,
}: {
hasError: boolean;
errors: Map<HTMLDivElement, ErrorMatcherPattern[]>;
}) => JSX.Element;
}

export default function FoldableLogger({
style,
bodyStyle,
logStyle = {},
log,
children,
matchers = defaultMatchers,
errorMatchers = defaultErrorMatchers,
autoScroll = false,
Expand All @@ -43,8 +54,15 @@ export default function FoldableLogger({
const bodyRef = useRef<HTMLDivElement>(null);
const spliter = React.useMemo(() => new Spliter(matchers), [matchers]);
const errorMatcher = React.useMemo(() => new ErrorMatcher(errorMatchers), [errorMatchers]);
const [errors, setErrors] = useState(new Map<HTMLDivElement, ErrorMatcherPattern[]>());

const setErrorRefs = useCallback((error: ErrorMatcherPattern[], ref: HTMLDivElement) => {
setErrors(err => produce(err, draft => {
draft.set(ref as any, error);
}));
}, [setErrors]);

const foldedLogger = spliter.execute(log);
const foldedLogger = React.useMemo(() => spliter.execute(log), [spliter, log]);

useEffect(() => {
if (autoScrollFlag && bodyRef.current) {
Expand Down Expand Up @@ -80,25 +98,28 @@ export default function FoldableLogger({
}

return (
<div className={styles.logMain} style={style}>
{showHeader ? <div className={styles.logHeader}>
<button className={styles.rawLog}>
{_('rawLog')}
</button>
</div> : null}
<ErrorContext.Provider value={{ setErrorRefs }}>
<div className={`${styles.logMain} ${errors.size ? styles.hasError : ''}`} style={style}>
{showHeader ? <div className={styles.logHeader}>
<button className={styles.rawLog}>
{_('rawLog')}
</button>
</div> : null}

<div className={styles.logBody} style={bodyStyle} ref={bodyRef}>
{/* <Search defaultSearch /> */}
<MemorizedLogContent
particals={foldedLogger}
style={logStyle}
linkify={linkify}
errorMatcher={errorMatcher}
/>
</div>
<div className={styles.logFooter} onClick={scrollBodyToTop}>
<a className={styles.backToTop}>{_('top')}</a>
<div className={styles.logBody} style={bodyStyle} ref={bodyRef}>
{/* <Search defaultSearch /> */}
<MemorizedLogContent
particals={foldedLogger}
style={logStyle}
linkify={linkify}
errorMatcher={errorMatcher}
/>
</div>
<div className={styles.logFooter} onClick={scrollBodyToTop}>
<a className={styles.backToTop}>{_('top')}</a>
</div>
</div>
</div>
{errors.size && children ? children({ hasError: !!errors.size, errors }) : null}
</ErrorContext.Provider>
);
}
2 changes: 0 additions & 2 deletions src/model/ErrorContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,8 @@ export function setErrorRefs(errors: ErrorMatcherPattern[], ref: HTMLDivElement)
errorRefs.set(ref, errors);
}


export { errorRefs };

export const ErrorContext = createContext({
refs: errorRefs,
setErrorRefs,
});
4 changes: 4 additions & 0 deletions src/style/log.module.less
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@
display: block;
}

.hasError {
margin-right: 240px;
}

.logHeader {
height: 28px;
padding: 0.7em 0.8em 0.6em;
Expand Down

0 comments on commit dcb9e21

Please sign in to comment.