From 7c363f1730f64ed633b8f4583ed3213f13979f42 Mon Sep 17 00:00:00 2001 From: Spynder <19329095+Spynder@users.noreply.github.com> Date: Tue, 20 May 2025 00:09:57 +0300 Subject: [PATCH] underline --- package-lock.json | 172 ++++++++++++++++++++++- package.json | 1 + src/components/MarkdownEditor.tsx | 50 ++++++- src/pages/article/create.tsx | 3 +- src/pages/article/edit.tsx | 8 +- src/pages/sight/create.tsx | 32 +++-- src/pages/sight/edit.tsx | 166 +++++++++++++++------- yarn.lock | 224 +++++++++++++++--------------- 8 files changed, 468 insertions(+), 188 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6abb20a..dba709d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -54,6 +54,7 @@ "react-simple-maps": "^3.0.0", "react-simplemde-editor": "^5.2.0", "react-swipeable": "^7.0.2", + "rehype-raw": "^7.0.0", "three": "^0.175.0", "vite-plugin-svgr": "^4.3.0" }, @@ -6676,6 +6677,83 @@ "node": ">= 0.4" } }, + "node_modules/hast-util-from-parse5": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.3.tgz", + "integrity": "sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg==", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "devlop": "^1.0.0", + "hastscript": "^9.0.0", + "property-information": "^7.0.0", + "vfile": "^6.0.0", + "vfile-location": "^5.0.0", + "web-namespaces": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-parse-selector": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz", + "integrity": "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-raw": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-9.1.0.tgz", + "integrity": "sha512-Y8/SBAHkZGoNkpzqqfCldijcuUKh7/su31kEBp67cFY09Wy0mTRgtsLYsiIxMJxlu0f6AA5SUTbDR8K0rxnbUw==", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "@ungap/structured-clone": "^1.0.0", + "hast-util-from-parse5": "^8.0.0", + "hast-util-to-parse5": "^8.0.0", + "html-void-elements": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "parse5": "^7.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0", + "web-namespaces": "^2.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-raw/node_modules/entities": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.0.tgz", + "integrity": "sha512-aKstq2TDOndCn4diEyp9Uq/Flu2i1GlLkc6XIDQSDMuaFE3OPW5OphLCyQ5SpSJZTb4reN+kTcYru5yIfXoRPw==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/hast-util-raw/node_modules/parse5": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, "node_modules/hast-util-to-jsx-runtime": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz", @@ -6702,6 +6780,33 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hast-util-to-parse5": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-8.0.0.tgz", + "integrity": "sha512-3KKrV5ZVI8if87DVSi1vDeByYrkGzg4mEfeu4alwgmmIeARiBLKCZS2uw5Gb6nU9x9Yufyj3iudm6i7nl52PFw==", + "dependencies": { + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0", + "web-namespaces": "^2.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-parse5/node_modules/property-information": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz", + "integrity": "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/hast-util-whitespace": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", @@ -6714,6 +6819,22 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hastscript": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-9.0.1.tgz", + "integrity": "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==", + "dependencies": { + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-parse-selector": "^4.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/highlight.js": { "version": "10.7.3", "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", @@ -6768,6 +6889,15 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/html-void-elements": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", + "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/htmlparser2": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", @@ -11280,6 +11410,20 @@ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" }, + "node_modules/rehype-raw": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/rehype-raw/-/rehype-raw-7.0.0.tgz", + "integrity": "sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-raw": "^9.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/remark-gfm": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-1.0.0.tgz", @@ -12738,6 +12882,19 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/vfile-location": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-5.0.3.tgz", + "integrity": "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/vfile-message": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", @@ -12752,9 +12909,9 @@ } }, "node_modules/vite": { - "version": "4.5.13", - "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.13.tgz", - "integrity": "sha512-Hgp8IF/yZDzKsN1hQWOuQZbrKiaFsbQud+07jJ8h9m9PaHWkpvZ5u55Xw5yYjWRXwRQ4jwFlJvY7T7FUJG9MCA==", + "version": "4.5.14", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.14.tgz", + "integrity": "sha512-+v57oAaoYNnO3hIu5Z/tJRZjq5aHM2zDve9YZ8HngVHbhk66RStobhb1sqPMIPEleV6cNKYK4eGrAbE9Ulbl2g==", "dev": true, "dependencies": { "esbuild": "^0.18.10", @@ -12840,6 +12997,15 @@ "defaults": "^1.0.3" } }, + "node_modules/web-namespaces": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz", + "integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/webgl-constants": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/webgl-constants/-/webgl-constants-1.1.1.tgz", diff --git a/package.json b/package.json index bfa73a5..c1c6702 100644 --- a/package.json +++ b/package.json @@ -50,6 +50,7 @@ "react-simple-maps": "^3.0.0", "react-simplemde-editor": "^5.2.0", "react-swipeable": "^7.0.2", + "rehype-raw": "^7.0.0", "three": "^0.175.0", "vite-plugin-svgr": "^4.3.0" }, diff --git a/src/components/MarkdownEditor.tsx b/src/components/MarkdownEditor.tsx index 263b0fd..6f682cd 100644 --- a/src/components/MarkdownEditor.tsx +++ b/src/components/MarkdownEditor.tsx @@ -1,6 +1,6 @@ import {styled} from '@mui/material/styles' import zIndex from '@mui/material/styles/zIndex' -import SimpleMDE, {SimpleMDEReactProps} from 'react-simplemde-editor' +import SimpleMDE, {SimpleMDEReactProps, default as SimpleMDEDefault} from 'react-simplemde-editor' const StyledMarkdownEditor = styled('div')(({theme}) => ({ '& .editor-toolbar': { @@ -63,10 +63,46 @@ const StyledMarkdownEditor = styled('div')(({theme}) => ({ '& .guide': { display: 'none', }, -})) +})); -export const MarkdownEditor = (props: SimpleMDEReactProps) => ( - - - -) +export const MarkdownEditor = (props: SimpleMDEReactProps) => { + if(props.options) + props.options.toolbar = [ + "bold", + "italic", + "strikethrough", + { + name: "Underline", + action: (editor: any) => { + + const cm = editor.codemirror; + let output = ''; + const selectedText = cm.getSelection(); + const text = selectedText ?? 'placeholder'; + + output = '' + text + ''; + cm.replaceSelection(output); + + }, + className: "fa fa-underline", // Look for a suitable icon + title: "Underline (Ctrl/Cmd-Alt-U)", + }, + "heading", + "quote", + "unordered-list", + "ordered-list", + "link", + "image", + "code", + "table", + "horizontal-rule", + "preview", + "fullscreen", + "guide" + ] + return ( + + + + ) +} diff --git a/src/pages/article/create.tsx b/src/pages/article/create.tsx index ec3c59f..f4875e6 100644 --- a/src/pages/article/create.tsx +++ b/src/pages/article/create.tsx @@ -9,6 +9,7 @@ import "easymde/dist/easymde.min.css"; import { LanguageSelector } from "@ui"; import { observer } from "mobx-react-lite"; import { EVERY_LANGUAGE, Languages, languageStore, META_LANGUAGE } from "@stores"; +import rehypeRaw from "rehype-raw"; const MemoizedSimpleMDE = React.memo(MarkdownEditor); @@ -208,7 +209,7 @@ export const ArticleCreate = observer(() => { }, }} > - {preview} + {preview} diff --git a/src/pages/article/edit.tsx b/src/pages/article/edit.tsx index 315534d..d7bd3bb 100644 --- a/src/pages/article/edit.tsx +++ b/src/pages/article/edit.tsx @@ -13,6 +13,8 @@ import "easymde/dist/easymde.min.css"; import { EVERY_LANGUAGE, Languages, languageStore, META_LANGUAGE } from "@stores"; import { observer } from "mobx-react-lite"; import { LanguageSelector, MediaView } from "@ui"; +import rehypeRaw from "rehype-raw"; + const MemoizedSimpleMDE = React.memo(MarkdownEditor); export const ArticleEdit = observer(() => { @@ -48,6 +50,10 @@ export const ArticleEdit = observer(() => { const bodyContent = watch("body"); const headingContent = watch("heading"); + useEffect(() => { + console.log(bodyContent) + }, [bodyContent]) + useEffect(() => { console.log(articleData) }, [articleData]) @@ -232,7 +238,7 @@ export const ArticleEdit = observer(() => { }, }} > - {bodyContent} + {bodyContent} {/* Привязанные медиа */} diff --git a/src/pages/sight/create.tsx b/src/pages/sight/create.tsx index ae445c9..b2d4666 100644 --- a/src/pages/sight/create.tsx +++ b/src/pages/sight/create.tsx @@ -3,6 +3,7 @@ import { Create, useAutocomplete } from "@refinedev/mui"; import { useForm } from "@refinedev/react-hook-form"; import { Controller, FieldValues } from "react-hook-form"; import React, { useState, useEffect } from "react"; +import { ArticleItem, articleFields } from "./types"; import { TOKEN_KEY } from "@providers"; import { observer } from "mobx-react-lite"; import { EVERY_LANGUAGE, Languages, languageStore, cityStore } from "@stores"; @@ -504,40 +505,47 @@ export const SightCreate = observer(() => { ( option.id === field.value - ) ?? null + ) || null } onChange={(_, value) => { - field.onChange(value?.id ?? ""); + console.log(value, _) + field.onChange(value?.id || ""); }} getOptionLabel={(item) => { - return item ? item.heading : ""; + return item ? item.media_name : ""; }} isOptionEqualToValue={(option, value) => { return option.id === value?.id; }} filterOptions={(options, { inputValue }) => { - return options.filter((option) => - option.heading - .toLowerCase() - .includes(inputValue.toLowerCase()) + return options.filter( + (option) => + option.media_name + .toLowerCase() + .includes(inputValue.toLowerCase()) && + [1,2,5,6].includes(option.media_type) ); }} renderInput={(params) => ( { + //setPreviewSelected(true); + //setSelectedMediaIndex(-1); + }} label="Медиа-предпросмотр" margin="normal" variant="outlined" - error={!!errors.preview_article} - helperText={(errors as any)?.preview_article?.message} + error={!!errors.arms} + helperText={(errors as any)?.arms?.message} /> )} /> diff --git a/src/pages/sight/edit.tsx b/src/pages/sight/edit.tsx index ecd47ed..084e2e5 100644 --- a/src/pages/sight/edit.tsx +++ b/src/pages/sight/edit.tsx @@ -207,10 +207,24 @@ export const SightEdit = observer(() => { const selectedMedia = mediaAutocompleteProps.options.find( (option) => option.id === previewMediaId ); + console.log("Triggering", previewMediaId) if(!selectedMedia) return; setMediaFile(selectedMedia); } - }, [previewMediaId]); + }, [previewMediaId, mediaAutocompleteProps.options]); + + // useEffect(() => { + // const selectedWatermarkLU = mediaAutocompleteProps.options.find( + // (option) => option.id === watermarkLUContent + // ); + // setWatermarkLUPreview( + // selectedWatermarkLU + // ? `${import.meta.env.VITE_KRBL_MEDIA}${ + // selectedWatermarkLU.id + // }/download?token=${localStorage.getItem(TOKEN_KEY)}` + // : null + // ); + // }, [watermarkLUContent, ]); const addressContent = watch("address"); const latitudeContent = watch("latitude"); @@ -397,6 +411,55 @@ export const SightEdit = observer(() => { name="name" /> + + ( + option.id === field.value + ) || null + } + onChange={(_, value) => { + field.onChange(value?.id || ""); + }} + getOptionLabel={(item) => { + return item ? item.media_name : ""; + }} + isOptionEqualToValue={(option, value) => { + return option.id === value?.id; + }} + filterOptions={(options, { inputValue }) => { + return options.filter( + (option) => + option.media_name + .toLowerCase() + .includes(inputValue.toLowerCase()) + ); + }} + renderInput={(params) => ( + { + //setPreviewSelected(true); + //setSelectedMediaIndex(-1); + }} + label="Медиа-предпросмотр" + margin="normal" + variant="outlined" + error={!!errors.arms} + helperText={(errors as any)?.arms?.message} + /> + )} + /> + )} + /> + + { ( - option.id === field.value - ) || null - } - onChange={(_, value) => { - field.onChange(value?.id || ""); - }} - getOptionLabel={(item) => { - return item ? item.media_name : ""; - }} - isOptionEqualToValue={(option, value) => { - return option.id === value?.id; - }} - filterOptions={(options, { inputValue }) => { - return options.filter( - (option) => - option.media_name - .toLowerCase() - .includes(inputValue.toLowerCase()) && - [1,2,5,6].includes(option.media_type) - ); - }} - renderInput={(params) => ( - { - //setPreviewSelected(true); - //setSelectedMediaIndex(-1); - }} - label="Медиа-предпросмотр" - margin="normal" - variant="outlined" - error={!!errors.arms} - helperText={(errors as any)?.arms?.message} - /> - )} - /> - )} - /> + control={control} + name="preview_media" + defaultValue={null} + render={({ field }) => ( + option.id === field.value + ) || null + } + onChange={(_, value) => { + console.log(value, _) + field.onChange(value?.id || ""); + }} + getOptionLabel={(item) => { + return item ? item.media_name : ""; + }} + isOptionEqualToValue={(option, value) => { + return option.id === value?.id; + }} + filterOptions={(options, { inputValue }) => { + return options.filter( + (option) => + option.media_name + .toLowerCase() + .includes(inputValue.toLowerCase()) && + [1,2,5,6].includes(option.media_type) + ); + }} + renderInput={(params) => ( + { + //setPreviewSelected(true); + //setSelectedMediaIndex(-1); + }} + label="Медиа-предпросмотр" + margin="normal" + variant="outlined" + error={!!errors.arms} + helperText={(errors as any)?.arms?.message} + /> + )} + /> + )} + /> @@ -971,13 +1035,13 @@ export const SightEdit = observer(() => { { @@ -1059,7 +1123,7 @@ export const SightEdit = observer(() => { )} - +