Skip to content

Commit

Permalink
fix: embed errorMatchesh
Browse files Browse the repository at this point in the history
  • Loading branch information
RaoHai committed Sep 8, 2020
1 parent f6c75e2 commit e4c8490
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 43 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.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
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>
);
}
29 changes: 22 additions & 7 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
* 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';

Expand All @@ -13,6 +14,8 @@ 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,29 +29,40 @@ export interface FoldableLoggerProps {
autoScroll?: boolean;
showHeader?: boolean;
linkify?: boolean;
setErrorRefs?: (errors: ErrorMatcherPattern[], ref: HTMLDivElement) => void;
children: ({
hasError,
errors,
}: {
hasError: boolean;
errors: Map<HTMLDivElement, ErrorMatcherPattern[]>;
}) => JSX.Element;
}

function noop() {}

export default function FoldableLogger({
style,
bodyStyle,
logStyle = {},
log,
children,
matchers = defaultMatchers,
errorMatchers = defaultErrorMatchers,
autoScroll = false,
showHeader = false,
linkify = true,
setErrorRefs = noop,
}: FoldableLoggerProps) {
const [autoScrollFlag, setAutoScrollFlag] = useState(autoScroll);
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 @@ -85,7 +99,7 @@ export default function FoldableLogger({

return (
<ErrorContext.Provider value={{ setErrorRefs }}>
<div className={styles.logMain} style={style}>
<div className={`${styles.logMain} ${errors.size ? styles.hasError : ''}`} style={style}>
{showHeader ? <div className={styles.logHeader}>
<button className={styles.rawLog}>
{_('rawLog')}
Expand All @@ -105,6 +119,7 @@ export default function FoldableLogger({
<a className={styles.backToTop}>{_('top')}</a>
</div>
</div>
{errors.size && children ? children({ hasError: !!errors.size, errors }) : null}
</ErrorContext.Provider>
);
}
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 e4c8490

Please sign in to comment.