Skip to content

Commit

Permalink
feat: replace anchorme with linkify-it (#25)
Browse files Browse the repository at this point in the history
  • Loading branch information
mattrothenberg authored Feb 9, 2022
1 parent 5bbba37 commit cd365cd
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 44 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
"@storybook/addons": "^6.1.21",
"@storybook/react": "^6.1.21",
"@types/d3": "^6.3.0",
"@types/linkify-it": "^3.0.2",
"@types/react": "^17.0.3",
"@types/react-dom": "^17.0.2",
"@types/react-virtualized": "^9.21.11",
Expand Down Expand Up @@ -101,12 +102,12 @@
"@types/lodash": "^4.0.6",
"@types/react-virtualized-auto-sizer": "^1.0.0",
"@types/react-window": "^1.8.2",
"anchorme": "^2.1.2",
"d3": "^6.6.0",
"date-fns": "^2.19.0",
"dompurify": "^2.2.9",
"downshift": "^6.1.1",
"immer": "^9.0.12",
"linkify-it": "^3.0.3",
"lodash": "^4.17.21",
"lodash-es": "^4.17.21",
"match-sorter": "^6.3.0",
Expand Down
82 changes: 44 additions & 38 deletions src/components/cell.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import React, { useEffect } from 'react';
import { areEqual } from 'react-window';
import tw, { TwStyle } from 'twin.macro';
import anchorme from 'anchorme';
import Linkify from 'linkify-it';
import { cellTypeMap } from '../store';
import { DashIcon, DiffModifiedIcon, PlusIcon } from '@primer/octicons-react';
import DOMPurify from 'dompurify';
import { EditableCell } from './editable-cell';

const linkify = Linkify().add('ftp:', null).add('mailto:', null);

interface CellProps {
type: string;
value: any;
Expand Down Expand Up @@ -47,37 +49,39 @@ export const Cell = React.memo(function (props: CellProps) {
onFocusChange,
background,
style = {},
onMouseEnter = () => { },
onMouseEnter = () => {},
} = props;

// @ts-ignore
const cellInfo = cellTypeMap[type];

const { cell: CellComponent } = cellInfo || {}
const { cell: CellComponent } = cellInfo || {};

const displayValue = (formattedValue || value || "").toString();
const displayValue = (formattedValue || value || '').toString();
const isLongValue = (displayValue || '').length > 23;
const stringWithLinks = React.useMemo(
() => displayValue ? (
DOMPurify.sanitize(
anchorme({
input: displayValue + '',
options: {
attributes: {
target: '_blank',
rel: 'noopener',
},
},
})
)
) : "",
[value]
)
const stringWithLinks = React.useMemo(() => {
if (!displayValue) return '';

const sanitized = DOMPurify.sanitize(displayValue);
// Does the sanitized string contain any links?
if (!linkify.test(sanitized)) return sanitized;

// If so, we need to linkify it.
const matches = linkify.match(sanitized);

// If there are no matches, we can just return the sanitized string.
if (!matches || matches.length === 0) return sanitized;

// Otherwise, let's naively use the first match.
return `<a href="${matches[0].url}" target="_blank" rel="noopener">
${matches[0].url}
</a>`;
}, [value]);

useEffect(() => {
if (!isFocused) return
onMouseEnter()
}, [isFocused])
if (!isFocused) return;
onMouseEnter();
}, [isFocused]);

if (!cellInfo) return null;

Expand All @@ -91,14 +95,15 @@ export const Cell = React.memo(function (props: CellProps) {
'modified-row': DiffModifiedIcon,
}[status || ''];
const statusColor =
isFirstColumn &&
// @ts-ignore
{
new: 'text-green-400',
old: 'text-pink-400',
modified: 'text-yellow-500',
'modified-row': 'text-yellow-500',
}[status || ''] || ""
(isFirstColumn &&
// @ts-ignore
{
new: 'text-green-400',
old: 'text-pink-400',
modified: 'text-yellow-500',
'modified-row': 'text-yellow-500',
}[status || '']) ||
'';

return (
<div
Expand All @@ -109,12 +114,13 @@ export const Cell = React.memo(function (props: CellProps) {
status === 'old' && tw`border-pink-200`,
status === 'modified' && tw`border-yellow-200`,
status === 'modified-row' && tw`border-gray-200`,
!status && tw`border-gray-200`
!status && tw`border-gray-200`,
]}
style={{
...style,
background: background || '#fff',
}}>
}}
>
<EditableCell
value={rawValue}
isEditable={isEditable}
Expand All @@ -123,7 +129,8 @@ export const Cell = React.memo(function (props: CellProps) {
isFocused={isFocused}
isExtraBlankRow={isExtraBlankRow}
onFocusChange={onFocusChange}
onRowDelete={onRowDelete}>
onRowDelete={onRowDelete}
>
<CellInner
value={value}
isFirstColumn={isFirstColumn}
Expand All @@ -143,7 +150,6 @@ export const Cell = React.memo(function (props: CellProps) {
);
}, areEqual);


const CellInner = React.memo(function CellInner({
value,
isFirstColumn,
Expand Down Expand Up @@ -176,7 +182,7 @@ const CellInner = React.memo(function CellInner({
css={[
tw`w-full h-full flex flex-none items-center px-4`,
typeof value === 'undefined' ||
(Number.isNaN(value) && tw`text-gray-300`),
(Number.isNaN(value) && tw`text-gray-300`),
]}
onMouseEnter={() => onMouseEnter?.()}
>
Expand Down Expand Up @@ -214,5 +220,5 @@ const CellInner = React.memo(function CellInner({
</div>
)}
</div>
)
})
);
});
22 changes: 17 additions & 5 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3251,6 +3251,11 @@
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.8.tgz#edf1bf1dbf4e04413ca8e5b17b3b7d7d54b59818"
integrity sha512-YSBPTLTVm2e2OoQIDYx8HaeWJ5tTToLH67kXR7zYNGupXMEHa2++G8k+DczX2cFVgalypqtyZIcU19AFcmOpmg==

"@types/linkify-it@^3.0.2":
version "3.0.2"
resolved "https://registry.yarnpkg.com/@types/linkify-it/-/linkify-it-3.0.2.tgz#fd2cd2edbaa7eaac7e7f3c1748b52a19143846c9"
integrity sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA==

"@types/lodash@^4.0.6":
version "4.14.171"
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.171.tgz#f01b3a5fe3499e34b622c362a46a609fdb23573b"
Expand Down Expand Up @@ -3837,11 +3842,6 @@ alphanum-sort@^1.0.0, alphanum-sort@^1.0.2:
resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3"
integrity sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=

anchorme@^2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/anchorme/-/anchorme-2.1.2.tgz#4abc7e128a8a42d0036a61ebb9b18bbc032fa52a"
integrity sha512-2iPY3kxDDZvtRzauqKDb4v7a5sTF4GZ+esQTY8nGYvmhAtGTeFPMn4cRnvyWS1qmtPTP0Mv8hyLOp9l3ZzWMKg==

ansi-align@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.0.tgz#b536b371cf687caaef236c18d3e21fe3797467cb"
Expand Down Expand Up @@ -9793,6 +9793,13 @@ lines-and-columns@^1.1.6:
resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00"
integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=

linkify-it@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-3.0.3.tgz#a98baf44ce45a550efb4d49c769d07524cc2fa2e"
integrity sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==
dependencies:
uc.micro "^1.0.1"

load-json-file@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b"
Expand Down Expand Up @@ -14795,6 +14802,11 @@ ua-parser-js@^0.7.18:
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.28.tgz#8ba04e653f35ce210239c64661685bf9121dec31"
integrity sha512-6Gurc1n//gjp9eQNXjD9O3M/sMwVtN5S8Lv9bvOYBfKfDNiIIhqiyi01vMBO45u4zkDE420w/e0se7Vs+sIg+g==

uc.micro@^1.0.1:
version "1.0.6"
resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac"
integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==

unbox-primitive@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471"
Expand Down

0 comments on commit cd365cd

Please sign in to comment.