diff --git a/src/components/EditorTextArea.js b/src/components/EditorTextArea.js
index 9c26796..5507aa0 100644
--- a/src/components/EditorTextArea.js
+++ b/src/components/EditorTextArea.js
@@ -1,17 +1,27 @@
-import { useState, useRef } from 'react';
+import { useState, useEffect, useRef } from 'react';
import styled from 'styled-components';
import ReactEditor from 'react-simple-code-editor';
import EditorPrismStyle from './EditorPrismStyle';
import { getHighlighter } from '../util/highlighting';
export default function EditorTextArea({ code, setCode, language, fontSize }) {
+ const [isSelected, toggleSelected] = useSelectedLine();
const highlight = getHighlighter(language);
function highlightWithLineNumbers(input, grammar) {
return highlight(input, grammar)
.split('\n')
- .map((line, i) => `${i + 1}${line}`)
- .join('\n');
+ .map((line, i) => (
+
+
+ pointer-events: auto;
+ cursor: pointer;
+`;
+
+const HighlightedLineNumber = styled(PlainLineNumber)`
+ color: ${props => props.theme.editor.lineNumberHl};
+ background-color: ${props => props.theme.editor.lineNumberHlBackground};
+ font-weight: bold;
+`;
+
+function useSelectedLine() {
+ // extract highlighted lines from window hash
+ const [selected, setSelected] = useState(() => {
+ const hash = window.location.hash;
+ if (/^#L\d+(-\d+)?$/.test(hash)) {
+ const [start, end] = hash.substring(2).split('-').map(Number);
+ return [start, isNaN(end) ? -1 : end];
+ } else {
+ return [-1, -1];
+ }
+ });
+
+ // update window hash when a new line is highlighted
+ useEffect(() => {
+ if (selected[0] !== -1) {
+ if (selected[1] !== -1) {
+ const [s, e] = selected.sort();
+ window.location.hash = `#L${s}-${e}`;
+ } else {
+ window.location.hash = `#L${selected[0]}`;
+ }
+ }
+ }, [selected]);
+
+ // toggle the highlighting for a given line
+ function toggleSelected(lineNo, shift) {
+ if (selected[0] === lineNo && selected[1] === -1) {
+ setSelected([-1, -1]);
+ } else if (selected[0] === -1 || !shift) {
+ setSelected([lineNo, -1]);
+ } else {
+ setSelected([selected[0], lineNo]);
+ }
+ }
+
+ // should a line be highlighted in the viewer?
+ function isSelected(lineNo) {
+ if (selected[0] === -1) {
+ return false;
+ }
+ if (selected[1] === -1) {
+ return selected[0] === lineNo;
+ }
+
+ return lineNo >= Math.min(...selected) && lineNo <= Math.max(...selected);
+ }
+
+ return [isSelected, toggleSelected];
+}
+
const KEYCODE_ENTER = 13;
const KEYCODE_PARENS = 57;
const KEYCODE_PARENS_CLOSE = 48;
diff --git a/src/style/themes.js b/src/style/themes.js
index 9a811d8..eee9af4 100644
--- a/src/style/themes.js
+++ b/src/style/themes.js
@@ -7,6 +7,8 @@ const themes = {
editor: {
background: 'none',
lineNumber: '#cccccc',
+ lineNumberHl: 'black',
+ lineNumberHlBackground: '#e0f6ff',
primary: 'black',
selection: '#b3d4fc',
comment: 'slategray',
@@ -33,6 +35,8 @@ const themes = {
editor: {
background: '#041f29',
lineNumber: '#81969A',
+ lineNumberHl: '#fff',
+ lineNumberHlBackground: '#0e303e',
primary: '#E0E2E4',
selection: '#E0E2E4',
comment: '#7D8C93',