Skip to content

Commit

Permalink
MatchesURL property(draft)
Browse files Browse the repository at this point in the history
  • Loading branch information
YYsuni committed Nov 14, 2023
1 parent 54a00d5 commit 23620fc
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 69 deletions.
37 changes: 15 additions & 22 deletions src/components/json-node.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import {
isReactComponent,
safeCall,
stringifyForCopying,
resolveEvalFailedNewValue
resolveEvalFailedNewValue,
customMatchesURL
} from '../utils'
import ObjectNode from './object-node'
import LongString from './long-string'
Expand All @@ -31,8 +32,7 @@ interface Props {
}

export default function JsonNode({ node, depth, deleteHandle: _deleteHandle, indexOrName, parent, editHandle }: Props) {
const { collapseStringsAfterLength, enableClipboard, editable, src, onDelete, onChange, customizeNode } =
useContext(JsonViewContext)
const { collapseStringsAfterLength, enableClipboard, editable, src, onDelete, onChange, customizeNode, matchesURL, urlRegExp } = useContext(JsonViewContext)

let customReturn: ReturnType<CustomizeNode> | undefined
if (typeof customizeNode === 'function') customReturn = safeCall(customizeNode, [{ node, depth, indexOrName }])
Expand Down Expand Up @@ -132,33 +132,26 @@ export default function JsonNode({ node, depth, deleteHandle: _deleteHandle, ind

const Icons = (
<>
{isEditing && (
<DoneSVG
className='json-view--edit'
style={{ display: 'inline-block' }}
onClick={deleting ? deleteHandle : done}
/>
)}
{isEditing && <DoneSVG className='json-view--edit' style={{ display: 'inline-block' }} onClick={deleting ? deleteHandle : done} />}
{isEditing && <CancelSVG className='json-view--edit' style={{ display: 'inline-block' }} onClick={cancel} />}

{!isEditing && enableClipboard && customCopy(customReturn as CustomizeOptions | undefined) && (
<CopyButton node={node} />
{!isEditing && enableClipboard && customCopy(customReturn as CustomizeOptions | undefined) && <CopyButton node={node} />}
{!isEditing && matchesURL && type === 'string' && urlRegExp.test(node) && customMatchesURL(customReturn as CustomizeOptions | undefined) && (
<span className='json-view--copy'>♣︎</span>
)}

{!isEditing && editableEdit(editable) && customEdit(customReturn as CustomizeOptions | undefined) && editHandle && (
<EditSVG className='json-view--edit' onClick={edit} />
)}
{!isEditing && editableDelete(editable) && customDelete(customReturn as CustomizeOptions | undefined) && _deleteHandle && (
<DeleteSVG className='json-view--edit' onClick={() => setDeleting(true)} />
)}
{!isEditing &&
editableEdit(editable) &&
customEdit(customReturn as CustomizeOptions | undefined) &&
editHandle && <EditSVG className='json-view--edit' onClick={edit} />}
{!isEditing &&
editableDelete(editable) &&
customDelete(customReturn as CustomizeOptions | undefined) &&
_deleteHandle && <DeleteSVG className='json-view--edit' onClick={() => setDeleting(true)} />}
</>
)

let className = 'json-view--string'

if (typeof (customReturn as CustomizeOptions)?.className === 'string')
className += ' ' + (customReturn as CustomizeOptions).className
if (typeof (customReturn as CustomizeOptions)?.className === 'string') className += ' ' + (customReturn as CustomizeOptions).className

switch (type) {
case 'number':
Expand Down
54 changes: 24 additions & 30 deletions src/components/json-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,12 @@ import { createContext, useCallback, useState } from 'react'
import JsonNode from './json-node'
import type { Collapsed, CustomizeNode, DisplaySize, Editable } from '../types'

type OnEdit = (params: {
newValue: any
oldValue: any
depth: number
src: any
indexOrName: string | number
parentType: 'object' | 'array'
}) => void
type OnDelete = (params: {
value: any
indexOrName: string | number
depth: number
src: any
parentType: 'object' | 'array'
}) => void
type OnEdit = (params: { newValue: any; oldValue: any; depth: number; src: any; indexOrName: string | number; parentType: 'object' | 'array' }) => void
type OnDelete = (params: { value: any; indexOrName: string | number; depth: number; src: any; parentType: 'object' | 'array' }) => void
type OnAdd = (params: { indexOrName: string | number; depth: number; src: any; parentType: 'object' | 'array' }) => void
type OnChange = (params: {
indexOrName: string | number
depth: number
src: any
parentType: 'object' | 'array'
type: 'add' | 'edit' | 'delete'
}) => void
type OnChange = (params: { indexOrName: string | number; depth: number; src: any; parentType: 'object' | 'array'; type: 'add' | 'edit' | 'delete' }) => void

export const defaultURLRegExp = /^(((ht|f)tps?):\/\/)?([^!@#$%^&*?.\s-]([^!@#$%^&*?.\s]{0,63}[^!@#$%^&*?.\s])?\.)+[a-z]{2,6}\/?/

export const JsonViewContext = createContext({
src: undefined as any,
Expand All @@ -47,7 +30,10 @@ export const JsonViewContext = createContext({

customizeNode: undefined as CustomizeNode | undefined,

displaySize: undefined as DisplaySize
displaySize: undefined as DisplaySize,

matchesURL: false,
urlRegExp: defaultURLRegExp
})

interface Props {
Expand All @@ -72,10 +58,13 @@ interface Props {
dark?: boolean
theme?: 'default' | 'a11y' | 'github' | 'vscode' | 'atom' | 'winter-is-coming'

displaySize?: DisplaySize,
displaySize?: DisplaySize

style?: React.CSSProperties,
style?: React.CSSProperties
className?: string

matchesURL?: boolean
urlRegExp?: RegExp
}

export default function JsonView({
Expand Down Expand Up @@ -103,7 +92,10 @@ export default function JsonView({
displaySize,

style,
className
className,

matchesURL = false,
urlRegExp = defaultURLRegExp
}: Props) {
const [_, update] = useState(0)
const forceUpdate = useCallback(() => update(state => ++state), [])
Expand Down Expand Up @@ -131,12 +123,14 @@ export default function JsonView({

customizeNode,

displaySize
displaySize,

matchesURL,
urlRegExp
}}>
<code
className={'json-view' + (dark ? ' dark' : '') + (theme && theme !== 'default' ? ' json-view_' + theme : '') + (className ? (' '+ className) : '')}
style={style}
>
className={'json-view' + (dark ? ' dark' : '') + (theme && theme !== 'default' ? ' json-view_' + theme : '') + (className ? ' ' + className : '')}
style={style}>
<JsonNode node={src} depth={1} />
</code>
</JsonViewContext.Provider>
Expand Down
11 changes: 9 additions & 2 deletions src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import JsonView from './components/json-view'
import JsonView, { defaultURLRegExp } from './components/json-view'
import { stringifyForCopying as stringify } from './utils'

export { JsonView as default, stringify }
import { ReactComponent as EditSVG } from './svgs/edit.svg'
import { ReactComponent as DeleteSVG } from './svgs/trash.svg'
import { ReactComponent as DoneSVG } from './svgs/done.svg'
import { ReactComponent as CancelSVG } from './svgs/cancel.svg'
import { ReactComponent as CopySVG } from './svgs/copy.svg'
import { ReactComponent as CopiedSVG } from './svgs/copied.svg'

export { JsonView as default, stringify, defaultURLRegExp, EditSVG, DeleteSVG, DoneSVG, CancelSVG, CopySVG, CopiedSVG }
29 changes: 22 additions & 7 deletions src/stories/json-view.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -204,13 +204,7 @@ export const BigObject: StoryObj<TYPE_FC> = {

export const Array: StoryObj<TYPE_FC> = {
args: {
src: [
'string',
123456,
false,
null,
{ string: 'string', number: 123456, boolean: false, null: null, Date: new Date(), Symbol: Symbol('JSON View') }
],
src: ['string', 123456, false, null, { string: 'string', number: 123456, boolean: false, null: null, Date: new Date(), Symbol: Symbol('JSON View') }],
collapsed: 1
}
}
Expand Down Expand Up @@ -422,3 +416,24 @@ export const CustomizeNode: StoryObj<TYPE_FC> = {
)
]
}

export const MatchesURL: StoryObj<TYPE_FC> = {
args: {
src: {
string: 'string',
longString: 'long string long string long string long string long string long string',
number: 123456,
boolean: false,
null: null,
func: function () {},
Symbol: Symbol('JSON View'),
obj: {
k1: 123,
k2: '123',
k3: false
},
arr: ['string', 123456, false, null]
},
matchesURL: true
}
}
10 changes: 8 additions & 2 deletions src/stories/share.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,18 @@ export const argTypes = {
defaultValue: { summary: false }
}
},
matchesURL: {
control: 'boolean',
description: 'Boolean',
table: {
defaultValue: { summary: false }
}
},
editable: {
table: {
defaultValue: { summary: false }
},
description:
'When set to true, you can add, edit, or delete the property, and the actions will trigger onAdd, onEdit, or onDelete. Options is available.'
description: 'When set to true, you can add, edit, or delete the property, and the actions will trigger onAdd, onEdit, or onDelete. Options is available.'
},
onAdd: {
description: `(params: { indexOrName: string | number, depth: number, src: any; parentType: 'object' | 'array' }) => void`
Expand Down
8 changes: 2 additions & 6 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,7 @@ export declare type Collapsed =
| undefined
| number
| boolean
| ((params: {
node: Record<string, any> | Array<any>
indexOrName: number | string | undefined
depth: number
size: number
}) => boolean | void)
| ((params: { node: Record<string, any> | Array<any>; indexOrName: number | string | undefined; depth: number; size: number }) => boolean | void)

export type DisplaySize = undefined | number | boolean | 'collapsed' | 'expanded'

Expand All @@ -24,6 +19,7 @@ export declare type CustomizeOptions = {
edit?: boolean
delete?: boolean
enableClipboard?: boolean
matchesURL?: boolean
collapsed?: boolean
className?: string
}
Expand Down
3 changes: 3 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,9 @@ export function customDelete(customOptions?: CustomizeOptions) {
export function customCopy(customOptions?: CustomizeOptions) {
return !customOptions || customOptions.enableClipboard === undefined || !!customOptions.enableClipboard
}
export function customMatchesURL(customOptions?: CustomizeOptions) {
return !customOptions || customOptions.matchesURL === undefined || !!customOptions.matchesURL
}

export function resolveEvalFailedNewValue(type: string, value: string) {
if (type === 'string') {
Expand Down

2 comments on commit 23620fc

@vercel
Copy link

@vercel vercel bot commented on 23620fc Nov 14, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vercel
Copy link

@vercel vercel bot commented on 23620fc Nov 14, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

react18-json-view – ./

react18-json-view.vercel.app
react18-json-view-yysuni.vercel.app
react18-json-view-git-main-yysuni.vercel.app

Please sign in to comment.