mirror of
https://github.com/inventree/InvenTree.git
synced 2025-04-28 11:36:44 +00:00
[PUI] Implement Notes editor (#5529)
* Add react-simplemde-editor React wrapper for simplemde which we already use * Barebones implementation of markdown editor field * Implement notes editor * Implement drag-and-drop image uplaod
This commit is contained in:
parent
7e753523d1
commit
816b60850d
@ -31,6 +31,7 @@
|
|||||||
"@tanstack/react-query": "^4.33.0",
|
"@tanstack/react-query": "^4.33.0",
|
||||||
"axios": "^1.5.0",
|
"axios": "^1.5.0",
|
||||||
"dayjs": "^1.11.9",
|
"dayjs": "^1.11.9",
|
||||||
|
"easymde": "^2.18.0",
|
||||||
"embla-carousel-react": "^8.0.0-rc12",
|
"embla-carousel-react": "^8.0.0-rc12",
|
||||||
"html5-qrcode": "^2.3.8",
|
"html5-qrcode": "^2.3.8",
|
||||||
"mantine-datatable": "^2.9.13",
|
"mantine-datatable": "^2.9.13",
|
||||||
@ -39,6 +40,7 @@
|
|||||||
"react-grid-layout": "^1.3.4",
|
"react-grid-layout": "^1.3.4",
|
||||||
"react-router-dom": "^6.15.0",
|
"react-router-dom": "^6.15.0",
|
||||||
"react-select": "^5.7.4",
|
"react-select": "^5.7.4",
|
||||||
|
"react-simplemde-editor": "^5.2.0",
|
||||||
"zustand": "^4.4.1"
|
"zustand": "^4.4.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
165
src/frontend/src/components/widgets/MarkdownEditor.tsx
Normal file
165
src/frontend/src/components/widgets/MarkdownEditor.tsx
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
import { t } from '@lingui/macro';
|
||||||
|
import { showNotification } from '@mantine/notifications';
|
||||||
|
import EasyMDE from 'easymde';
|
||||||
|
import 'easymde/dist/easymde.min.css';
|
||||||
|
import { ReactNode, useCallback, useMemo } from 'react';
|
||||||
|
import { useState } from 'react';
|
||||||
|
import SimpleMDE from 'react-simplemde-editor';
|
||||||
|
|
||||||
|
import { api } from '../../App';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Markdon editor component. Uses react-simplemde-editor
|
||||||
|
*/
|
||||||
|
export function MarkdownEditor({
|
||||||
|
data,
|
||||||
|
allowEdit,
|
||||||
|
saveValue
|
||||||
|
}: {
|
||||||
|
data?: string;
|
||||||
|
allowEdit?: boolean;
|
||||||
|
saveValue?: (value: string) => void;
|
||||||
|
}): ReactNode {
|
||||||
|
const [value, setValue] = useState(data);
|
||||||
|
|
||||||
|
// Construct markdown editor options
|
||||||
|
const options = useMemo(() => {
|
||||||
|
// Custom set of toolbar icons for the editor
|
||||||
|
let icons: any[] = ['preview', 'side-by-side'];
|
||||||
|
|
||||||
|
if (allowEdit) {
|
||||||
|
icons.push(
|
||||||
|
'|',
|
||||||
|
|
||||||
|
// Heading icons
|
||||||
|
'heading-1',
|
||||||
|
'heading-2',
|
||||||
|
'heading-3',
|
||||||
|
'|',
|
||||||
|
|
||||||
|
// Font styles
|
||||||
|
'bold',
|
||||||
|
'italic',
|
||||||
|
'strikethrough',
|
||||||
|
'|',
|
||||||
|
|
||||||
|
// Text formatting
|
||||||
|
'unordered-list',
|
||||||
|
'ordered-list',
|
||||||
|
'code',
|
||||||
|
'quote',
|
||||||
|
'|',
|
||||||
|
|
||||||
|
// Link and image icons
|
||||||
|
'table',
|
||||||
|
'link',
|
||||||
|
'image'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allowEdit) {
|
||||||
|
icons.push(
|
||||||
|
'|',
|
||||||
|
|
||||||
|
// Save button
|
||||||
|
{
|
||||||
|
name: 'save',
|
||||||
|
action: (editor: EasyMDE) => {
|
||||||
|
if (saveValue) {
|
||||||
|
saveValue(editor.value());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
className: 'fa fa-save',
|
||||||
|
title: t`Save`
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
minHeight: '400px',
|
||||||
|
toolbar: icons,
|
||||||
|
sideBySideFullscreen: false,
|
||||||
|
uploadImage: allowEdit,
|
||||||
|
imagePathAbsolute: true,
|
||||||
|
imageUploadFunction: (
|
||||||
|
file: File,
|
||||||
|
onSuccess: (url: string) => void,
|
||||||
|
onError: (error: string) => void
|
||||||
|
) => {
|
||||||
|
api
|
||||||
|
.post(
|
||||||
|
'/notes-image-upload/',
|
||||||
|
{
|
||||||
|
image: file
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'multipart/form-data'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then((response) => {
|
||||||
|
if (response.data?.image) {
|
||||||
|
onSuccess(response.data.image);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
showNotification({
|
||||||
|
title: t`Error`,
|
||||||
|
message: t`Failed to upload image`,
|
||||||
|
color: 'red'
|
||||||
|
});
|
||||||
|
onError(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}, [allowEdit]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SimpleMDE
|
||||||
|
value={value}
|
||||||
|
options={options}
|
||||||
|
onChange={(v: string) => setValue(v)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom implementation of the MarkdownEditor widget for editing notes.
|
||||||
|
* Includes a callback hook for saving the notes to the server.
|
||||||
|
*/
|
||||||
|
export function NotesEditor({
|
||||||
|
url,
|
||||||
|
data,
|
||||||
|
allowEdit
|
||||||
|
}: {
|
||||||
|
url: string;
|
||||||
|
data?: string;
|
||||||
|
allowEdit?: boolean;
|
||||||
|
}): ReactNode {
|
||||||
|
// Callback function to upload data to the server
|
||||||
|
const uploadData = useCallback((value: string) => {
|
||||||
|
api
|
||||||
|
.patch(url, { notes: value })
|
||||||
|
.then((response) => {
|
||||||
|
showNotification({
|
||||||
|
title: t`Success`,
|
||||||
|
message: t`Notes saved`,
|
||||||
|
color: 'green'
|
||||||
|
});
|
||||||
|
return response;
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
showNotification({
|
||||||
|
title: t`Error`,
|
||||||
|
message: t`Failed to save notes`,
|
||||||
|
color: 'red'
|
||||||
|
});
|
||||||
|
return error;
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<MarkdownEditor data={data} allowEdit={allowEdit} saveValue={uploadData} />
|
||||||
|
);
|
||||||
|
}
|
@ -35,6 +35,10 @@ import { api } from '../../App';
|
|||||||
import { PanelGroup, PanelType } from '../../components/nav/PanelGroup';
|
import { PanelGroup, PanelType } from '../../components/nav/PanelGroup';
|
||||||
import { AttachmentTable } from '../../components/tables/AttachmentTable';
|
import { AttachmentTable } from '../../components/tables/AttachmentTable';
|
||||||
import { StockItemTable } from '../../components/tables/stock/StockItemTable';
|
import { StockItemTable } from '../../components/tables/stock/StockItemTable';
|
||||||
|
import {
|
||||||
|
MarkdownEditor,
|
||||||
|
NotesEditor
|
||||||
|
} from '../../components/widgets/MarkdownEditor';
|
||||||
import { editPart } from '../../functions/forms/PartForms';
|
import { editPart } from '../../functions/forms/PartForms';
|
||||||
|
|
||||||
export default function PartDetail() {
|
export default function PartDetail() {
|
||||||
@ -136,7 +140,7 @@ export default function PartDetail() {
|
|||||||
name: 'notes',
|
name: 'notes',
|
||||||
label: t`Notes`,
|
label: t`Notes`,
|
||||||
icon: <IconNotes size="18" />,
|
icon: <IconNotes size="18" />,
|
||||||
content: <Text>part notes go here</Text>
|
content: partNotesTab()
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}, [part]);
|
}, [part]);
|
||||||
@ -167,6 +171,17 @@ export default function PartDetail() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function partNotesTab(): React.ReactNode {
|
||||||
|
// TODO: Set edit permission based on user permissions
|
||||||
|
return (
|
||||||
|
<NotesEditor
|
||||||
|
url={`/part/${part.pk}/`}
|
||||||
|
data={part.notes ?? ''}
|
||||||
|
allowEdit={true}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function partStockTab(): React.ReactNode {
|
function partStockTab(): React.ReactNode {
|
||||||
return (
|
return (
|
||||||
<StockItemTable
|
<StockItemTable
|
||||||
|
@ -1196,6 +1196,18 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@babel/types" "^7.20.7"
|
"@babel/types" "^7.20.7"
|
||||||
|
|
||||||
|
"@types/codemirror@^5.60.4", "@types/codemirror@~5.60.5":
|
||||||
|
version "5.60.10"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/codemirror/-/codemirror-5.60.10.tgz#ac836a3ac20483988a0507cdbbaeb6ee0affa1e6"
|
||||||
|
integrity sha512-ZTA3teiCWKT8HUUofqlGPlShu5ojdIajizsS0HpH6GL0/iEdjRt7fXbCLHHqKYP5k7dC/HnnWIjZAiELUwBdjQ==
|
||||||
|
dependencies:
|
||||||
|
"@types/tern" "*"
|
||||||
|
|
||||||
|
"@types/estree@*":
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.1.tgz#aa22750962f3bf0e79d753d3cc067f010c95f194"
|
||||||
|
integrity sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==
|
||||||
|
|
||||||
"@types/history@^4.7.11":
|
"@types/history@^4.7.11":
|
||||||
version "4.7.11"
|
version "4.7.11"
|
||||||
resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.11.tgz#56588b17ae8f50c53983a524fc3cc47437969d64"
|
resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.11.tgz#56588b17ae8f50c53983a524fc3cc47437969d64"
|
||||||
@ -1220,6 +1232,11 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@types/istanbul-lib-report" "*"
|
"@types/istanbul-lib-report" "*"
|
||||||
|
|
||||||
|
"@types/marked@^4.0.7":
|
||||||
|
version "4.3.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/marked/-/marked-4.3.1.tgz#45fb6dfd47afb595766c71ed7749ead23f137de3"
|
||||||
|
integrity sha512-vSSbKZFbNktrQ15v7o1EaH78EbWV+sPQbPjHG+Cp8CaNcPFUEfjZ0Iml/V0bFDwsTlYe8o6XC5Hfdp91cqPV2g==
|
||||||
|
|
||||||
"@types/node@*", "@types/node@^20.5.9":
|
"@types/node@*", "@types/node@^20.5.9":
|
||||||
version "20.5.9"
|
version "20.5.9"
|
||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.5.9.tgz#a70ec9d8fa0180a314c3ede0e20ea56ff71aed9a"
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.5.9.tgz#a70ec9d8fa0180a314c3ede0e20ea56ff71aed9a"
|
||||||
@ -1287,6 +1304,13 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.3.tgz#cef09e3ec9af1d63d2a6cc5b383a737e24e6dcf5"
|
resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.3.tgz#cef09e3ec9af1d63d2a6cc5b383a737e24e6dcf5"
|
||||||
integrity sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==
|
integrity sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==
|
||||||
|
|
||||||
|
"@types/tern@*":
|
||||||
|
version "0.23.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/tern/-/tern-0.23.4.tgz#03926eb13dbeaf3ae0d390caf706b2643a0127fb"
|
||||||
|
integrity sha512-JAUw1iXGO1qaWwEOzxTKJZ/5JxVeON9kvGZ/osgZaJImBnyjyn0cjovPsf6FNLmyGY8Vw9DoXZCMlfMkMwHRWg==
|
||||||
|
dependencies:
|
||||||
|
"@types/estree" "*"
|
||||||
|
|
||||||
"@types/yargs-parser@*":
|
"@types/yargs-parser@*":
|
||||||
version "21.0.0"
|
version "21.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b"
|
resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b"
|
||||||
@ -1536,6 +1560,18 @@ clsx@^1.1.1:
|
|||||||
resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12"
|
resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12"
|
||||||
integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==
|
integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==
|
||||||
|
|
||||||
|
codemirror-spell-checker@1.1.2:
|
||||||
|
version "1.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/codemirror-spell-checker/-/codemirror-spell-checker-1.1.2.tgz#1c660f9089483ccb5113b9ba9ca19c3f4993371e"
|
||||||
|
integrity sha512-2Tl6n0v+GJRsC9K3MLCdLaMOmvWL0uukajNJseorZJsslaxZyZMgENocPU8R0DyoTAiKsyqiemSOZo7kjGV0LQ==
|
||||||
|
dependencies:
|
||||||
|
typo-js "*"
|
||||||
|
|
||||||
|
codemirror@^5.63.1:
|
||||||
|
version "5.65.15"
|
||||||
|
resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.65.15.tgz#66899278f44a7acde0eb641388cd563fe6dfbe19"
|
||||||
|
integrity sha512-YC4EHbbwQeubZzxLl5G4nlbLc1T21QTrKGaOal/Pkm9dVDMZXMH7+ieSPEOZCtO9I68i8/oteJKOxzHC2zR+0g==
|
||||||
|
|
||||||
color-convert@^1.9.0:
|
color-convert@^1.9.0:
|
||||||
version "1.9.3"
|
version "1.9.3"
|
||||||
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
|
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
|
||||||
@ -1667,6 +1703,17 @@ dom-helpers@^5.0.1:
|
|||||||
"@babel/runtime" "^7.8.7"
|
"@babel/runtime" "^7.8.7"
|
||||||
csstype "^3.0.2"
|
csstype "^3.0.2"
|
||||||
|
|
||||||
|
easymde@^2.18.0:
|
||||||
|
version "2.18.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/easymde/-/easymde-2.18.0.tgz#ff1397d07329b1a7b9187d2d0c20766fa16b3b1b"
|
||||||
|
integrity sha512-IxVVUxNWIoXLeqtBU4BLc+eS/ScYhT1Dcb6yF5Wchoj1iXAV+TIIDWx+NCaZhY7RcSHqDPKllbYq7nwGKILnoA==
|
||||||
|
dependencies:
|
||||||
|
"@types/codemirror" "^5.60.4"
|
||||||
|
"@types/marked" "^4.0.7"
|
||||||
|
codemirror "^5.63.1"
|
||||||
|
codemirror-spell-checker "1.1.2"
|
||||||
|
marked "^4.1.0"
|
||||||
|
|
||||||
electron-to-chromium@^1.4.477:
|
electron-to-chromium@^1.4.477:
|
||||||
version "1.4.508"
|
version "1.4.508"
|
||||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.508.tgz#5641ff2f5ba11df4bd960fe6a2f9f70aa8b9af96"
|
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.508.tgz#5641ff2f5ba11df4bd960fe6a2f9f70aa8b9af96"
|
||||||
@ -2146,6 +2193,11 @@ mantine-datatable@^2.9.13:
|
|||||||
resolved "https://registry.yarnpkg.com/mantine-datatable/-/mantine-datatable-2.9.13.tgz#2c94a8f3b596216b794f1c7881acc20150ab1186"
|
resolved "https://registry.yarnpkg.com/mantine-datatable/-/mantine-datatable-2.9.13.tgz#2c94a8f3b596216b794f1c7881acc20150ab1186"
|
||||||
integrity sha512-k0Q+FKC3kx7IiNJxeLP2PXJHVxuL704U5OVvtVYP/rexlPW8tqZud3WIZDuqfDCkZ83VYoszSTzauCssW+7mLw==
|
integrity sha512-k0Q+FKC3kx7IiNJxeLP2PXJHVxuL704U5OVvtVYP/rexlPW8tqZud3WIZDuqfDCkZ83VYoszSTzauCssW+7mLw==
|
||||||
|
|
||||||
|
marked@^4.1.0:
|
||||||
|
version "4.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/marked/-/marked-4.3.0.tgz#796362821b019f734054582038b116481b456cf3"
|
||||||
|
integrity sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==
|
||||||
|
|
||||||
memoize-one@^6.0.0:
|
memoize-one@^6.0.0:
|
||||||
version "6.0.0"
|
version "6.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-6.0.0.tgz#b2591b871ed82948aee4727dc6abceeeac8c1045"
|
resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-6.0.0.tgz#b2591b871ed82948aee4727dc6abceeeac8c1045"
|
||||||
@ -2497,6 +2549,13 @@ react-select@^5.7.4:
|
|||||||
react-transition-group "^4.3.0"
|
react-transition-group "^4.3.0"
|
||||||
use-isomorphic-layout-effect "^1.1.2"
|
use-isomorphic-layout-effect "^1.1.2"
|
||||||
|
|
||||||
|
react-simplemde-editor@^5.2.0:
|
||||||
|
version "5.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-simplemde-editor/-/react-simplemde-editor-5.2.0.tgz#7a4c8b97e4989cb129b45ba140145d71bdc0684e"
|
||||||
|
integrity sha512-GkTg1MlQHVK2Rks++7sjuQr/GVS/xm6y+HchZ4GPBWrhcgLieh4CjK04GTKbsfYorSRYKa0n37rtNSJmOzEDkQ==
|
||||||
|
dependencies:
|
||||||
|
"@types/codemirror" "~5.60.5"
|
||||||
|
|
||||||
react-style-singleton@^2.2.1:
|
react-style-singleton@^2.2.1:
|
||||||
version "2.2.1"
|
version "2.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/react-style-singleton/-/react-style-singleton-2.2.1.tgz#f99e420492b2d8f34d38308ff660b60d0b1205b4"
|
resolved "https://registry.yarnpkg.com/react-style-singleton/-/react-style-singleton-2.2.1.tgz#f99e420492b2d8f34d38308ff660b60d0b1205b4"
|
||||||
@ -2751,6 +2810,11 @@ typescript@^5.2.2:
|
|||||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.2.2.tgz#5ebb5e5a5b75f085f22bc3f8460fba308310fa78"
|
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.2.2.tgz#5ebb5e5a5b75f085f22bc3f8460fba308310fa78"
|
||||||
integrity sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==
|
integrity sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==
|
||||||
|
|
||||||
|
typo-js@*:
|
||||||
|
version "1.2.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/typo-js/-/typo-js-1.2.3.tgz#aa7fab3cfcc3bba01746df06fceb93b7f786c6ac"
|
||||||
|
integrity sha512-67Hyl94beZX8gmTap7IDPrG5hy2cHftgsCAcGvE1tzuxGT+kRB+zSBin0wIMwysYw8RUCBCvv9UfQl8TNM75dA==
|
||||||
|
|
||||||
unraw@^2.0.1:
|
unraw@^2.0.1:
|
||||||
version "2.0.1"
|
version "2.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/unraw/-/unraw-2.0.1.tgz#7b51dcdfb1e43d59d5e52cdb44d349d029edbaba"
|
resolved "https://registry.yarnpkg.com/unraw/-/unraw-2.0.1.tgz#7b51dcdfb1e43d59d5e52cdb44d349d029edbaba"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user