Highlight line that has error
This commit is contained in:
parent
bb8b2d3d2e
commit
db9677bcca
|
|
@ -25,7 +25,7 @@
|
||||||
"react-simple-code-editor": "^0.11.0",
|
"react-simple-code-editor": "^0.11.0",
|
||||||
"styled-components": "^5.2.0",
|
"styled-components": "^5.2.0",
|
||||||
"typescript": "~3.7.2",
|
"typescript": "~3.7.2",
|
||||||
"zwiftout": "^0.5.0"
|
"zwiftout": "^1.0.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"predeploy": "yarn build",
|
"predeploy": "yarn build",
|
||||||
|
|
|
||||||
14
src/App.tsx
14
src/App.tsx
|
|
@ -1,7 +1,7 @@
|
||||||
import React, { useState, useCallback } from "react";
|
import React, { useState, useCallback } from "react";
|
||||||
import { WorkoutPlot } from "./components/WorkoutPlot";
|
import { WorkoutPlot } from "./components/WorkoutPlot";
|
||||||
import { WorkoutStats } from "./components/WorkoutStats";
|
import { WorkoutStats } from "./components/WorkoutStats";
|
||||||
import { parse } from "zwiftout";
|
import { parse, ParseError, ValidationError, ZwiftoutException } from "zwiftout";
|
||||||
import { ErrorMessage } from "./components/ErrorMessage";
|
import { ErrorMessage } from "./components/ErrorMessage";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import { CodeEditor } from "./components/CodeEditor";
|
import { CodeEditor } from "./components/CodeEditor";
|
||||||
|
|
@ -32,7 +32,7 @@ const AppContainer = styled.div`
|
||||||
export function App() {
|
export function App() {
|
||||||
const [text, setText] = useState(defaultWorkout);
|
const [text, setText] = useState(defaultWorkout);
|
||||||
const [workout, setWorkout] = useState(parse(defaultWorkout));
|
const [workout, setWorkout] = useState(parse(defaultWorkout));
|
||||||
const [error, setError] = useState<string | undefined>(undefined);
|
const [error, setError] = useState<ZwiftoutException | undefined>(undefined);
|
||||||
|
|
||||||
const onChange = useCallback(
|
const onChange = useCallback(
|
||||||
(value: string) => {
|
(value: string) => {
|
||||||
|
|
@ -41,7 +41,11 @@ export function App() {
|
||||||
setWorkout(parse(value));
|
setWorkout(parse(value));
|
||||||
setError(undefined);
|
setError(undefined);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
setError(e.message);
|
if (e instanceof ParseError || e instanceof ValidationError) {
|
||||||
|
setError(e);
|
||||||
|
} else {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[setText, setWorkout, setError],
|
[setText, setWorkout, setError],
|
||||||
|
|
@ -50,9 +54,9 @@ export function App() {
|
||||||
return (
|
return (
|
||||||
<AppContainer>
|
<AppContainer>
|
||||||
<AppTitle />
|
<AppTitle />
|
||||||
<CodeEditor onValueChange={onChange} value={text} />
|
<CodeEditor onValueChange={onChange} value={text} error={error} />
|
||||||
<WorkoutPlot intervals={workout.intervals} />
|
<WorkoutPlot intervals={workout.intervals} />
|
||||||
{error && <ErrorMessage>{error}</ErrorMessage>}
|
{error && <ErrorMessage>{error.message}</ErrorMessage>}
|
||||||
<WorkoutStats workout={workout} />
|
<WorkoutStats workout={workout} />
|
||||||
<ZwoOutput workout={workout} />
|
<ZwoOutput workout={workout} />
|
||||||
<Credits />
|
<Credits />
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
|
import React, { useCallback } from "react";
|
||||||
import Editor from "react-simple-code-editor";
|
import Editor from "react-simple-code-editor";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
|
import { ZwiftoutException } from "zwiftout";
|
||||||
|
|
||||||
const highlight = (code: string): string => {
|
const highlight = (code: string): string => {
|
||||||
return code
|
return code
|
||||||
|
|
@ -11,7 +13,7 @@ const highlight = (code: string): string => {
|
||||||
.replace(/@(.*?)$/gm, "<code class='comment-start'>@</code><code class='comment'>$1</code>");
|
.replace(/@(.*?)$/gm, "<code class='comment-start'>@</code><code class='comment'>$1</code>");
|
||||||
};
|
};
|
||||||
|
|
||||||
export const CodeEditor = styled(Editor).attrs({ padding: 10, highlight })`
|
export const BaseCodeEditor = styled(Editor).attrs({ padding: 10 })`
|
||||||
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace;
|
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
line-height: 1.3;
|
line-height: 1.3;
|
||||||
|
|
@ -46,4 +48,26 @@ export const CodeEditor = styled(Editor).attrs({ padding: 10, highlight })`
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
color: #888;
|
color: #888;
|
||||||
}
|
}
|
||||||
|
code.error {
|
||||||
|
background-color: rgba(252, 152, 152, 0.5);
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const highlightErrorLine = (code: string, linenr: number): string => {
|
||||||
|
const regex = new RegExp(`^((?:[^\\n]*?\\n){${linenr}})([^\\n]*?)\\n`);
|
||||||
|
return code.replace(regex, "$1<code class='error'>$2</code>\n");
|
||||||
|
};
|
||||||
|
|
||||||
|
interface CodeEditorProps {
|
||||||
|
value: string;
|
||||||
|
onValueChange: (value: string) => void;
|
||||||
|
error: ZwiftoutException | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const CodeEditor: React.FC<CodeEditorProps> = ({ value, onValueChange, error }) => {
|
||||||
|
const highlightFn = useCallback((code: string) => highlight(error ? highlightErrorLine(code, error.loc.row) : code), [
|
||||||
|
error,
|
||||||
|
]);
|
||||||
|
return <BaseCodeEditor value={value} onValueChange={onValueChange} highlight={highlightFn} />;
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -11075,10 +11075,10 @@ yargs@^13.3.0, yargs@^13.3.2:
|
||||||
y18n "^4.0.0"
|
y18n "^4.0.0"
|
||||||
yargs-parser "^13.1.2"
|
yargs-parser "^13.1.2"
|
||||||
|
|
||||||
zwiftout@^0.5.0:
|
zwiftout@^1.0.0:
|
||||||
version "0.5.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/zwiftout/-/zwiftout-0.5.0.tgz#ca46fa1e0f16fba185bce97ba8f1d3674011ceff"
|
resolved "https://registry.yarnpkg.com/zwiftout/-/zwiftout-1.0.0.tgz#58dd2f2cf556e97a8a0b7385a2429f4cb2f5fabf"
|
||||||
integrity sha512-GHHd8N27l5AfYs36tl8a5n4sMos8kw7zI5ojA6K3tbyrLRyPAk2EF439CubK0XX5ad0JLr9gnpZwzKrNo5Kd2A==
|
integrity sha512-N1IOERpuInNUwTn8vL97lH/Tuwy8wjTE2XhUybBplmmK9AcPSgSx2Ll4fQXnGHEtEG0Sen5ev9Kv3lgQrdmReQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
argparse "^2.0.1"
|
argparse "^2.0.1"
|
||||||
ramda "^0.27.1"
|
ramda "^0.27.1"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue