Skip to content

Commit

Permalink
feat: allow pasting from other sheet sources (e.g. Google Sheets) (#18)
Browse files Browse the repository at this point in the history
  • Loading branch information
imballinst authored Oct 30, 2022
1 parent 5b18e38 commit aafe55c
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 5 deletions.
25 changes: 21 additions & 4 deletions src/components/Editor/MarkdownEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,19 @@ import {
} from '../../store/inspect';
import './MarkdownEditor.css';
import { useStore } from '@nanostores/solid';
import { extractNumberFromKey, isCtrlOrCmdKey, isNumberHeadings } from '../../utils/key-parser';
import {
extractNumberFromKey,
isCtrlOrCmdKey,
isNumberHeadings
} from '../../utils/parsers/keycode';
import { ParsedStringResult, parseTableString } from '../../utils/operators/table';
import { markdownStore, setMarkdown } from '../../store/markdown';
import { setAlert } from '../../store/alert';
import { modifyTextSelection, Toolbar } from './Toolbar';
import { ToolbarAction } from '../../utils/operators/toolbar';
import { Button } from '../Button';
import { getToolbarHoverText } from './Toolbar/common';
import { parseTableFromTabbedText } from '../../utils/parsers/table';

export const MarkdownEditor = () => {
const markdown = useStore(markdownStore);
Expand Down Expand Up @@ -73,7 +78,7 @@ export const MarkdownEditor = () => {
setInspectStatus(InspectStatus.InspectingSnippet);
setPrevSelected([selectionStart, selectionEnd]);
setSelected(undefined);
}
};

const onKeyDown: JSX.TextareaHTMLAttributes<HTMLTextAreaElement>['onKeyDown'] = (e) => {
const { selectionStart, selectionEnd } = e.currentTarget;
Expand Down Expand Up @@ -118,7 +123,7 @@ export const MarkdownEditor = () => {
}
case '`': {
e.preventDefault();
onInspectElement()
onInspectElement();
break;
}
default: {
Expand Down Expand Up @@ -185,7 +190,19 @@ export const MarkdownEditor = () => {
}
}}
onInput={(e) => {
setMarkdown(e.currentTarget.value ?? '');
const nextValue = e.currentTarget.value ?? '';
setMarkdown(nextValue);
}}
onPaste={(e) => {
e.preventDefault();
const pasted = e.clipboardData?.getData('text/plain');
const parseResult = parseTableFromTabbedText(pasted);
if (parseResult) {
const selectionStart = e.currentTarget.selectionStart;
setMarkdown((prev) =>
prev.slice(0, selectionStart).concat(parseResult).concat(prev.slice(selectionStart))
);
}
}}
/>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
} from '../../../../utils/operators/table';
import { HeaderButton } from './HeaderButton';
import { Button } from '../../../Button';
import { isCtrlOrCmdKey } from '../../../../utils/key-parser';
import { isCtrlOrCmdKey } from '../../../../utils/parsers/keycode';
import { getToolbarHoverText } from '../../Toolbar/common';

const ARROW_UP_KEY = 'ArrowUp';
Expand Down
File renamed without changes.
49 changes: 49 additions & 0 deletions src/utils/parsers/table.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { describe, expect, test } from "vitest";
import { parseTableFromTabbedText } from "./table";

describe('parseTableFromTabbedText', () => {
test('invalid case: undefined', () => {
expect(parseTableFromTabbedText(undefined)).toBe(undefined)
})

test('invalid case: empty string', () => {
expect(parseTableFromTabbedText('')).toBe(undefined)
})

test('invalid case: no columns', () => {
expect(parseTableFromTabbedText('test')).toBe(undefined)
})

test('invalid case: different number of columns', () => {
const str = `
hello\tworld
this is an invalid table
`.trim()

expect(parseTableFromTabbedText(str)).toBe(undefined)
})

test('valid case', () => {
const str = `
hello\tworld
this is a valid table\they!
`.trim()

expect(parseTableFromTabbedText(str)).toBe(`
|hello|world|
|this is a valid table|hey!|
`.trim())
})

test('valid case, with pipe characters', () => {
const str = `
hello\tworld
this is a | valid table\they!
`.trim()

expect(parseTableFromTabbedText(str)).toBe(`
|hello|world|
|this is a \\| valid table|hey!|
`.trim())
})
})
10 changes: 10 additions & 0 deletions src/utils/parsers/table.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export function parseTableFromTabbedText(text: string | undefined): string | undefined {
if (!text) return undefined

const lines = text.split('\n')
const tabCountPerLine = lines.map(line => line.match(/\t/g)?.length || 0)
const allLinesHaveEqualTabCount = tabCountPerLine.every(tabCount => tabCount === tabCountPerLine[0] && tabCount > 0)

if (!allLinesHaveEqualTabCount) return undefined
return lines.map(line => `|${line.replace(/\|/g, '\\|').replace(/\t/g, '|')}|`).join('\n')
}

0 comments on commit aafe55c

Please sign in to comment.