feat(lab): Draft view pretty ok now
This commit is contained in:
parent
73163f5676
commit
929822b249
15 changed files with 327 additions and 29 deletions
|
@ -32,7 +32,7 @@
|
||||||
"react-copy-to-clipboard": "^5.0.4",
|
"react-copy-to-clipboard": "^5.0.4",
|
||||||
"react-hotkeys-hook": "^3.4.4",
|
"react-hotkeys-hook": "^3.4.4",
|
||||||
"react-instantsearch-dom": "^6.18.0",
|
"react-instantsearch-dom": "^6.18.0",
|
||||||
"react-markdown": "^7.1.1",
|
"react-markdown": "^8.0.0",
|
||||||
"react-swipeable": "^6.2.0",
|
"react-swipeable": "^6.2.0",
|
||||||
"react-timeago": "^6.2.1",
|
"react-timeago": "^6.2.1",
|
||||||
"rehype-highlight": "^5.0.1",
|
"rehype-highlight": "^5.0.1",
|
||||||
|
|
17
packages/freesewing.shared/components/json.js
Normal file
17
packages/freesewing.shared/components/json.js
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
import React from 'react'
|
||||||
|
import Highlight from 'shared/components/mdx/highlight.js'
|
||||||
|
import hljs from 'highlight.js/lib/common'
|
||||||
|
|
||||||
|
const Json = props => {
|
||||||
|
const code = props.js
|
||||||
|
? JSON.stringify(props.js, null, 2)
|
||||||
|
: props.children
|
||||||
|
|
||||||
|
return <Highlight
|
||||||
|
language='json'
|
||||||
|
raw={hljs.highlight(code, { language: 'json' }).value}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Json
|
||||||
|
|
|
@ -4,14 +4,23 @@ const names = {
|
||||||
js: 'javascript',
|
js: 'javascript',
|
||||||
bash: 'bash',
|
bash: 'bash',
|
||||||
sh: 'shell',
|
sh: 'shell',
|
||||||
|
json: 'JSON',
|
||||||
|
yaml: 'YAML',
|
||||||
}
|
}
|
||||||
|
|
||||||
const Highlight = (props) => {
|
const Highlight = (props) => {
|
||||||
|
|
||||||
const language = props.children
|
const language = props.language
|
||||||
|
? props.language
|
||||||
|
: props.children
|
||||||
? props.children.props.className.split('-').pop()
|
? props.children.props.className.split('-').pop()
|
||||||
: 'txt'
|
: 'txt'
|
||||||
|
|
||||||
|
const preProps = {
|
||||||
|
className: `language-${language} hljs text-base lg:text-lg whitespace-pre-wrap break-words`
|
||||||
|
}
|
||||||
|
if (props.raw) preProps.dangerouslySetInnerHTML = { __html: props.raw }
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="hljs my-4">
|
<div className="hljs my-4">
|
||||||
<div className={`
|
<div className={`
|
||||||
|
@ -24,7 +33,7 @@ const Highlight = (props) => {
|
||||||
<span>{names[language] ? names[language] : language}</span>
|
<span>{names[language] ? names[language] : language}</span>
|
||||||
<CopyToClipboard content={props.children} />
|
<CopyToClipboard content={props.children} />
|
||||||
</div>
|
</div>
|
||||||
<pre className={`language-${language} hljs text-base lg:text-lg whitespace-pre-wrap break-words`}>
|
<pre {...preProps}>
|
||||||
{props.children}
|
{props.children}
|
||||||
</pre>
|
</pre>
|
||||||
</div>
|
</div>
|
||||||
|
|
29
packages/freesewing.shared/components/robot/index.js
Normal file
29
packages/freesewing.shared/components/robot/index.js
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
import poses from './poses'
|
||||||
|
|
||||||
|
// pose is one of:
|
||||||
|
// fail,
|
||||||
|
// ohno,
|
||||||
|
// shrug,
|
||||||
|
// shrug2,
|
||||||
|
// yay
|
||||||
|
|
||||||
|
const Robot = ({
|
||||||
|
size = 124,
|
||||||
|
viewBox = '0 0 500 500',
|
||||||
|
className = '',
|
||||||
|
pose = 'yay',
|
||||||
|
color = false,
|
||||||
|
embed = false
|
||||||
|
}) => (
|
||||||
|
<svg
|
||||||
|
className={className || ''}
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width={embed ? '' : size || 124}
|
||||||
|
height={embed ? '' : size || 124}
|
||||||
|
viewBox={viewBox || '0 0 500 500'}
|
||||||
|
>
|
||||||
|
<path stroke="none" fill={color ? color : 'currentColor'} d={poses[pose]} />
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
|
||||||
|
export default Robot
|
18
packages/freesewing.shared/components/robot/poses.js
Normal file
18
packages/freesewing.shared/components/robot/poses.js
Normal file
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,15 @@
|
||||||
|
import Robot from 'shared/components/robot/index.js'
|
||||||
|
import Events from './events.js'
|
||||||
|
|
||||||
|
const Error = props => (
|
||||||
|
<div className="mt-12">
|
||||||
|
<div className="flex flex-row items-center justify-around">
|
||||||
|
<h1>{props.app.t('errors.something')}</h1>
|
||||||
|
<div className="max-w-96"><Robot pose='fail' embed/></div>
|
||||||
|
</div>
|
||||||
|
<Events events={props.patternInstance.events} />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
|
export default Error
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
import Markdown from 'react-markdown'
|
||||||
|
import { linkClasses } from 'shared/components/navigation/primary.js'
|
||||||
|
|
||||||
|
const eventBlock = events => events.join(" \n")
|
||||||
|
|
||||||
|
const EventGroup = ({ type='info', events=[] }) => events.length > 0 ? (
|
||||||
|
<div className="">
|
||||||
|
<h3 className="capitalize" id={`events-${type}`}>{type}</h3>
|
||||||
|
<div className="mdx">
|
||||||
|
<Markdown>{eventBlock(events)}</Markdown>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : null
|
||||||
|
|
||||||
|
const order = [
|
||||||
|
'error',
|
||||||
|
'warning',
|
||||||
|
'info',
|
||||||
|
'debug'
|
||||||
|
]
|
||||||
|
|
||||||
|
const Events = props => (
|
||||||
|
<div className="flex flex-col">
|
||||||
|
<ul className="flex flex-row row-wrap">
|
||||||
|
{order.map(type => (
|
||||||
|
<li key={type} className="">
|
||||||
|
<a href={`#events-${type}`} className={`text-secondary font-bold capitalize text-xl`}>{type}</a>
|
||||||
|
{type === 'debug' ? '' : <span className="px-2 font-bold">|</span>}
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
{order.map(type => <EventGroup type={type} events={props.events[type]} />)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
|
export default Events
|
|
@ -3,35 +3,86 @@ import Svg from './svg'
|
||||||
import Defs from './defs'
|
import Defs from './defs'
|
||||||
import Part from './part'
|
import Part from './part'
|
||||||
import theme from 'pkgs/plugin-theme/src/index.js'
|
import theme from 'pkgs/plugin-theme/src/index.js'
|
||||||
|
import Robot from 'shared/components/robot/index.js'
|
||||||
|
import Error from './error.js'
|
||||||
|
import Events from './events.js'
|
||||||
|
import Json from 'shared/components/json.js'
|
||||||
|
import Yaml from 'shared/components/yaml.js'
|
||||||
|
import { capitalize } from 'shared/utils.js'
|
||||||
|
|
||||||
const LabDraft = ({ app, pattern, gist, updateGist }) => {
|
const tabClasses = active => `
|
||||||
|
tab tab-bordered font-bold text-4xl pb-12 capitalize
|
||||||
|
${active && 'text-base-content tab-active'}
|
||||||
|
`
|
||||||
|
|
||||||
|
const Wrap = props => <div className="max-w-screen-xl m-auto">{props.children}</div>
|
||||||
|
|
||||||
|
const LabDraft = props => {
|
||||||
|
const { app, pattern, gist, updateGist } = props
|
||||||
|
|
||||||
|
const [tab, setTab] = useState(props.pattern.config.name)
|
||||||
|
|
||||||
const patternInstance = new pattern(gist)
|
const patternInstance = new pattern(gist)
|
||||||
if (gist?.renderer === 'svg') return <div
|
const eprops = { ...props, patternInstance }
|
||||||
dangerouslySetInnerHTML={{ __html: patternInstance.use(theme).draft().render()}} />
|
if (gist?.renderer === 'svg') patternInstance.use(theme)
|
||||||
|
// Catch errors
|
||||||
|
try { patternInstance.draft() }
|
||||||
|
catch(error) {
|
||||||
|
console.log('Failed to draft pattern', error)
|
||||||
|
return <Error error={error} {...eprops} at={'draft'} />
|
||||||
|
}
|
||||||
|
|
||||||
const patternProps = patternInstance.draft().getRenderProps()
|
// Render as SVG
|
||||||
console.log(patternProps)
|
let svg
|
||||||
|
try { svg = patternInstance.render() }
|
||||||
|
catch(error) {
|
||||||
|
console.log('Failed to render pattern', error)
|
||||||
|
return <Error error={error} {...eprops} />
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gist?.renderer === 'svg')
|
||||||
|
return <div dangerouslySetInnerHTML={{ __html: svg }} />
|
||||||
|
|
||||||
|
// Render as React
|
||||||
|
let patternProps = {}
|
||||||
|
try { patternProps = patternInstance.draft().getRenderProps() }
|
||||||
|
catch(error) {
|
||||||
|
console.log('Failed to get render props for pattern', error)
|
||||||
|
return <Error error={error} {...eprops} />
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Svg {...patternProps}>
|
<div>
|
||||||
<Defs {...patternProps} />
|
<div className="tabs my-8 mx-auto justify-center">
|
||||||
<style>{`:root { --pattern-scale: ${gist.scale || 1}}`}</style>
|
{[props.pattern.config.name, 'events', 'yaml', 'json'].map(name => <button
|
||||||
<g>
|
key={name}
|
||||||
{Object.keys(patternProps.parts).map((name) => (
|
onClick={() => setTab(name)}
|
||||||
<Part
|
className={tabClasses(tab === name)}
|
||||||
key={name}
|
>{name}</button>)}
|
||||||
part={patternProps.parts[name]}
|
</div>
|
||||||
locale={gist.locale}
|
{tab === 'events' && <Wrap><Events events={patternInstance.events} /></Wrap>}
|
||||||
paperless={gist.paperless}
|
{tab === 'json' && <Wrap><Json>{JSON.stringify(props.gist, null, 2)}</Json></Wrap>}
|
||||||
units={gist.units}
|
{tab === 'yaml' && <Wrap><Yaml json={JSON.stringify(props.gist, null, 2)} /></Wrap>}
|
||||||
name={name}
|
{tab === props.pattern.config.name && (
|
||||||
app={app}
|
<Svg {...patternProps}>
|
||||||
/>
|
<Defs {...patternProps} />
|
||||||
))}
|
<style>{`:root { --pattern-scale: ${gist.scale || 1}}`}</style>
|
||||||
</g>
|
<g>
|
||||||
</Svg>
|
{Object.keys(patternProps.parts).map((name) => (
|
||||||
|
<Part
|
||||||
|
key={name}
|
||||||
|
part={patternProps.parts[name]}
|
||||||
|
locale={gist.locale}
|
||||||
|
paperless={gist.paperless}
|
||||||
|
units={gist.units}
|
||||||
|
name={name}
|
||||||
|
app={app}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</g>
|
||||||
|
</Svg>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
import ClearIcon from 'shared/components/icons/clear.js'
|
||||||
|
import orderBy from 'lodash.orderby'
|
||||||
|
|
||||||
|
const CoreSettingOnly = props => {
|
||||||
|
const list = props.pattern.config.draftOrder
|
||||||
|
const partNames = list.map(part => ({ id: part, name: props.app.t(`parts.${part}`, props.app.locale) }))
|
||||||
|
|
||||||
|
const togglePart = part => {
|
||||||
|
const parts = props.gist.only || []
|
||||||
|
const newParts = new Set(parts)
|
||||||
|
if (newParts.has(part)) newParts.delete(part)
|
||||||
|
else newParts.add(part)
|
||||||
|
if (newParts.size < 1) reset()
|
||||||
|
else props.updateGist(['only'], [...newParts])
|
||||||
|
}
|
||||||
|
|
||||||
|
const reset = () => {
|
||||||
|
props.unsetGist(['only'])
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="py-4 mx-6 border-l-2 pl-2">
|
||||||
|
<p className="m-0 p-0 px-2 mb-2 text-neutral-content opacity-60 italic">
|
||||||
|
{props.app.t(`settings.only.description`)}
|
||||||
|
</p>
|
||||||
|
<div className="flex flex-row">
|
||||||
|
<div className="grow">
|
||||||
|
{orderBy(partNames, ['name'], ['asc']).map(part => (
|
||||||
|
<button
|
||||||
|
key={part.id}
|
||||||
|
onClick={() => togglePart(part.id)}
|
||||||
|
className={`
|
||||||
|
mr-1 mb-1 text-left text-lg w-full hover:text-secondary-focus px-2
|
||||||
|
${props.gist?.only && props.gist.only.indexOf(part.id) !== -1 && 'font-bold text-secondary'}
|
||||||
|
`}
|
||||||
|
>
|
||||||
|
<span className={`
|
||||||
|
text-3xl mr-2 inline-block p-0 leading-3
|
||||||
|
translate-y-3
|
||||||
|
`}>
|
||||||
|
<>°</>
|
||||||
|
</span>
|
||||||
|
{part.name}
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-row-reverse">
|
||||||
|
<button
|
||||||
|
title={props.app.t('app.reset')}
|
||||||
|
className="btn btn-ghost btn-xs text-accent"
|
||||||
|
disabled={!props.gist.only || props.gist.only.length < 1}
|
||||||
|
onClick={reset}
|
||||||
|
>
|
||||||
|
<ClearIcon />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CoreSettingOnly
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ const settings = {
|
||||||
complete: {
|
complete: {
|
||||||
dflt: false,
|
dflt: false,
|
||||||
},
|
},
|
||||||
|
only: { },
|
||||||
locale: {
|
locale: {
|
||||||
list: ['de', 'en', 'es', 'fr', 'nl'],
|
list: ['de', 'en', 'es', 'fr', 'nl'],
|
||||||
},
|
},
|
||||||
|
@ -35,6 +36,9 @@ const settings = {
|
||||||
svg: '@freesewing/core (SVG)'
|
svg: '@freesewing/core (SVG)'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
debug: {
|
||||||
|
dflt: false,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
const CoreSettings = props => {
|
const CoreSettings = props => {
|
||||||
|
|
|
@ -2,6 +2,7 @@ import { linkClasses, Chevron } from 'shared/components/navigation/primary.js'
|
||||||
import PctDegOption from 'shared/components/workbench/inputs/design-option-pct-deg'
|
import PctDegOption from 'shared/components/workbench/inputs/design-option-pct-deg'
|
||||||
import CountOption from 'shared/components/workbench/inputs/design-option-count'
|
import CountOption from 'shared/components/workbench/inputs/design-option-count'
|
||||||
import ListSetting from './core-setting-list'
|
import ListSetting from './core-setting-list'
|
||||||
|
import OnlySetting from './core-setting-only'
|
||||||
import MmSetting from './core-setting-mm'
|
import MmSetting from './core-setting-mm'
|
||||||
import BoolSetting from './core-setting-bool.js'
|
import BoolSetting from './core-setting-bool.js'
|
||||||
import SaBoolSetting from './core-setting-sa-bool.js'
|
import SaBoolSetting from './core-setting-sa-bool.js'
|
||||||
|
@ -23,6 +24,13 @@ const settings = {
|
||||||
</span>
|
</span>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
debug: props => {
|
||||||
|
return (
|
||||||
|
<span className="text-secondary">
|
||||||
|
{props.app.t(`app.${props.gist.debug ? 'yes' : 'no'}`)}
|
||||||
|
</span>
|
||||||
|
)
|
||||||
|
},
|
||||||
locale: props => {
|
locale: props => {
|
||||||
return (
|
return (
|
||||||
<span className="text-secondary">
|
<span className="text-secondary">
|
||||||
|
@ -56,6 +64,9 @@ const settings = {
|
||||||
{props.config.titles[props.gist.renderer]}
|
{props.config.titles[props.gist.renderer]}
|
||||||
</span>
|
</span>
|
||||||
),
|
),
|
||||||
|
only: props => (props.gist?.only && props.gist.only.lenght > 0)
|
||||||
|
? <span>{props.gist.only.length}</span>
|
||||||
|
: <span>fixme</span>
|
||||||
}
|
}
|
||||||
|
|
||||||
const inputs = {
|
const inputs = {
|
||||||
|
@ -82,13 +93,14 @@ const inputs = {
|
||||||
title: props.config.titles[key]
|
title: props.config.titles[key]
|
||||||
}))}
|
}))}
|
||||||
/>,
|
/>,
|
||||||
|
only: props => <OnlySetting {...props} />
|
||||||
}
|
}
|
||||||
|
|
||||||
const Setting = props => {
|
const Setting = props => {
|
||||||
|
|
||||||
if (props.setting === 'saBool')
|
if (props.setting === 'saBool')
|
||||||
return <SaBoolSetting {...props} {...props.config} />
|
return <SaBoolSetting {...props} {...props.config} />
|
||||||
if (['paperless', 'complete'].indexOf(props.setting) !== -1)
|
if (['paperless', 'complete', 'debug'].indexOf(props.setting) !== -1)
|
||||||
return <BoolSetting {...props} {...props.config} />
|
return <BoolSetting {...props} {...props.config} />
|
||||||
|
|
||||||
const Input = inputs[props.setting]
|
const Input = inputs[props.setting]
|
||||||
|
|
|
@ -102,8 +102,6 @@ const WorkbenchWrapper = ({ app, pattern }) => {
|
||||||
updateGist={updateGist}
|
updateGist={updateGist}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<pre>{JSON.stringify(mode, null, 2)}</pre>
|
|
||||||
<pre>{JSON.stringify(gist, null, 2)}</pre>
|
|
||||||
</Layout>
|
</Layout>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
19
packages/freesewing.shared/components/yaml.js
Normal file
19
packages/freesewing.shared/components/yaml.js
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
import React from 'react'
|
||||||
|
import Highlight from 'shared/components/mdx/highlight.js'
|
||||||
|
import hljs from 'highlight.js/lib/common'
|
||||||
|
|
||||||
|
import yaml from 'js-yaml'
|
||||||
|
const Yaml = props => {
|
||||||
|
let code
|
||||||
|
if (props.json) code = yaml.dump(JSON.parse(props.json))
|
||||||
|
else if (props.js) code = yaml.dump(props.js)
|
||||||
|
else code = props.children
|
||||||
|
|
||||||
|
return <Highlight
|
||||||
|
language='yaml'
|
||||||
|
raw={hljs.highlight(code, { language: 'yaml' }).value}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Yaml
|
||||||
|
|
|
@ -15,9 +15,10 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tailwindcss/typography": "^0.5.0",
|
"@tailwindcss/typography": "^0.5.0",
|
||||||
"daisyui": "^1.16.2",
|
"daisyui": "^1.16.2",
|
||||||
|
"highlight.js": "^11.4.0",
|
||||||
"lodash.orderby": "^4.6.0",
|
"lodash.orderby": "^4.6.0",
|
||||||
"lodash.unset": "^4.5.2",
|
"lodash.unset": "^4.5.2",
|
||||||
"react-markdown": "^7.1.1",
|
"react-markdown": "^8.0.0",
|
||||||
"react-timeago": "^6.2.1",
|
"react-timeago": "^6.2.1",
|
||||||
"rehype-highlight": "^5.0.1",
|
"rehype-highlight": "^5.0.1",
|
||||||
"remark-extract-frontmatter": "^3.2.0",
|
"remark-extract-frontmatter": "^3.2.0",
|
||||||
|
|
25
yarn.lock
25
yarn.lock
|
@ -14021,6 +14021,11 @@ highlight.js@^10.4.1:
|
||||||
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.7.3.tgz#697272e3991356e40c3cac566a74eef681756531"
|
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.7.3.tgz#697272e3991356e40c3cac566a74eef681756531"
|
||||||
integrity sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==
|
integrity sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==
|
||||||
|
|
||||||
|
highlight.js@^11.4.0:
|
||||||
|
version "11.4.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-11.4.0.tgz#34ceadd49e1596ee5aba3d99346cdfd4845ee05a"
|
||||||
|
integrity sha512-nawlpCBCSASs7EdvZOYOYVkJpGmAOKMYZgZtUqSRqodZE0GRVcFKwo1RcpeOemqh9hyttTdd5wDBwHkuSyUfnA==
|
||||||
|
|
||||||
highlight.js@~11.3.0:
|
highlight.js@~11.3.0:
|
||||||
version "11.3.1"
|
version "11.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-11.3.1.tgz#813078ef3aa519c61700f84fe9047231c5dc3291"
|
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-11.3.1.tgz#813078ef3aa519c61700f84fe9047231c5dc3291"
|
||||||
|
@ -22996,6 +23001,26 @@ react-markdown@^7.1.1:
|
||||||
unist-util-visit "^4.0.0"
|
unist-util-visit "^4.0.0"
|
||||||
vfile "^5.0.0"
|
vfile "^5.0.0"
|
||||||
|
|
||||||
|
react-markdown@^8.0.0:
|
||||||
|
version "8.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-markdown/-/react-markdown-8.0.0.tgz#3243296a59ddb0f451d262cc2e11123674b416c2"
|
||||||
|
integrity sha512-qbrWpLny6Ef2xHqnYqtot948LXP+4FtC+MWIuaN1kvSnowM+r1qEeEHpSaU0TDBOisQuj+Qe6eFY15cNL3gLAw==
|
||||||
|
dependencies:
|
||||||
|
"@types/hast" "^2.0.0"
|
||||||
|
"@types/unist" "^2.0.0"
|
||||||
|
comma-separated-tokens "^2.0.0"
|
||||||
|
hast-util-whitespace "^2.0.0"
|
||||||
|
prop-types "^15.0.0"
|
||||||
|
property-information "^6.0.0"
|
||||||
|
react-is "^17.0.0"
|
||||||
|
remark-parse "^10.0.0"
|
||||||
|
remark-rehype "^10.0.0"
|
||||||
|
space-separated-tokens "^2.0.0"
|
||||||
|
style-to-object "^0.3.0"
|
||||||
|
unified "^10.0.0"
|
||||||
|
unist-util-visit "^4.0.0"
|
||||||
|
vfile "^5.0.0"
|
||||||
|
|
||||||
react-moment-proptypes@^1.6.0, react-moment-proptypes@^1.7.0:
|
react-moment-proptypes@^1.6.0, react-moment-proptypes@^1.7.0:
|
||||||
version "1.8.1"
|
version "1.8.1"
|
||||||
resolved "https://registry.yarnpkg.com/react-moment-proptypes/-/react-moment-proptypes-1.8.1.tgz#7ba4076147f6b5998f0d4f51d302d6d8c62049fd"
|
resolved "https://registry.yarnpkg.com/react-moment-proptypes/-/react-moment-proptypes-1.8.1.tgz#7ba4076147f6b5998f0d4f51d302d6d8c62049fd"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue