diff --git a/public/error.svg b/public/error.svg
index a520a262..71d58e79 100644
--- a/public/error.svg
+++ b/public/error.svg
@@ -34,4 +34,4 @@
-
\ No newline at end of file
+
diff --git a/public/icons/editor-image-half-align-left.svg b/public/icons/editor-image-half-align-left.svg
new file mode 100644
index 00000000..61b9d858
--- /dev/null
+++ b/public/icons/editor-image-half-align-left.svg
@@ -0,0 +1,3 @@
+
diff --git a/public/icons/editor-image-half-align-right.svg b/public/icons/editor-image-half-align-right.svg
new file mode 100644
index 00000000..fe129bb6
--- /dev/null
+++ b/public/icons/editor-image-half-align-right.svg
@@ -0,0 +1,3 @@
+
diff --git a/public/icons/editor-squib.svg b/public/icons/editor-squib.svg
new file mode 100644
index 00000000..519a3975
--- /dev/null
+++ b/public/icons/editor-squib.svg
@@ -0,0 +1,3 @@
+
diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json
index 711e6c01..5175fa79 100644
--- a/public/locales/en/translation.json
+++ b/public/locales/en/translation.json
@@ -295,5 +295,7 @@
"number list": "number list",
"delimiter": "delimiter",
"cancel_low_caps": "cancel",
- "repeat": "repeat"
+ "repeat": "repeat",
+ "Add signature": "Add signature",
+ "Substrate": "Substrate"
}
diff --git a/public/locales/ru/translation.json b/public/locales/ru/translation.json
index 72a75569..862c6e7f 100644
--- a/public/locales/ru/translation.json
+++ b/public/locales/ru/translation.json
@@ -300,6 +300,7 @@
"sign up": "зарегистрироваться",
"sign up or sign in": "зарегистрироваться или войти",
"slug is used by another user": "Имя уже занято другим пользователем",
+ "squib": "Подверстка",
"terms of use": "правилами пользования сайтом",
"topics": "темы",
"user already exist": "пользователь уже существует",
@@ -316,5 +317,7 @@
"number list": "нумер. список",
"delimiter": "разделитель",
"cancel_low_caps": "отменить",
- "repeat": "повторить"
+ "repeat": "повторить",
+ "Add signature": "Добавить подпись",
+ "Substrate": "Подложка"
}
diff --git a/src/components/Article/Article.module.scss b/src/components/Article/Article.module.scss
index e7a90172..7ee1567c 100644
--- a/src/components/Article/Article.module.scss
+++ b/src/components/Article/Article.module.scss
@@ -372,15 +372,3 @@ img {
}
}
}
-
-[data-float] {
- max-width: 50%;
-}
-
-[data-float='left'] {
- float: left;
-}
-
-[data-float='right'] {
- float: right;
-}
diff --git a/src/components/Editor/BubbleMenu/BlockquoteBubbleMenu.tsx b/src/components/Editor/BubbleMenu/BlockquoteBubbleMenu.tsx
new file mode 100644
index 00000000..796a8d97
--- /dev/null
+++ b/src/components/Editor/BubbleMenu/BlockquoteBubbleMenu.tsx
@@ -0,0 +1,40 @@
+import type { Editor } from '@tiptap/core'
+import styles from './FigureBubbleMenu.module.scss'
+import { clsx } from 'clsx'
+import { Icon } from '../../_shared/Icon'
+import { useLocalize } from '../../../context/localize'
+
+type Props = {
+ editor: Editor
+ ref: (el: HTMLElement) => void
+}
+
+export const BlockquoteBubbleMenu = (props: Props) => {
+ return (
+
+ )
+}
diff --git a/src/components/Editor/BubbleMenu/FigureBubbleMenu.module.scss b/src/components/Editor/BubbleMenu/FigureBubbleMenu.module.scss
new file mode 100644
index 00000000..3cad51d7
--- /dev/null
+++ b/src/components/Editor/BubbleMenu/FigureBubbleMenu.module.scss
@@ -0,0 +1,107 @@
+.FigureBubbleMenu {
+ background: #000;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+
+ .bubbleMenuButton {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ flex-wrap: nowrap;
+ opacity: 0.5;
+ padding: 1rem;
+
+ .triangle {
+ margin-left: 4px;
+ }
+
+ img {
+ display: block;
+ }
+ }
+
+ .bubbleMenuButtonActive {
+ opacity: 1;
+ }
+
+ .delimiter {
+ background: #fff;
+ opacity: 0.5;
+ display: inline-block;
+ height: 1.4em;
+ margin: 0 0.2em;
+ vertical-align: text-bottom;
+ width: 1px;
+ }
+
+ .dropDownHolder {
+ position: relative;
+ cursor: pointer;
+ display: inline-flex;
+ flex-flow: row nowrap;
+ align-items: center;
+
+ .dropDown {
+ position: absolute;
+ padding: 6px;
+ top: calc(100% + 8px);
+ left: 50%;
+ transform: translateX(-50%);
+ box-shadow: 0 4px 10px rgb(0 0 0 / 25%);
+ background: #000;
+ color: #898c94;
+
+ & > header {
+ font-size: 10px;
+ border-bottom: 1px solid #898c94;
+ }
+
+ .actions {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ grid-gap: 10px;
+ margin-bottom: 8px;
+
+ .color {
+ width: 20px;
+ height: 20px;
+ border-radius: 50%;
+ border: 2px solid #3c3c3c;
+ background: #ccc;
+
+ &.yellow {
+ background: #f6e3a1;
+ }
+ &.white {
+ background: #fff;
+ box-shadow: inset 0 0 0 1px #000;
+ border-color: #fff;
+ }
+ &.yellow {
+ background: #f6e3a1;
+ }
+ &.pink {
+ background: #f1b5bc;
+ }
+ &.green {
+ background: #bfe9cb;
+ box-shadow: inset 0 0 0 1px #000;
+ border-color: #fff;
+ }
+ &.black {
+ background: #000;
+ }
+ }
+
+ &:last-child {
+ margin-bottom: 0;
+ }
+
+ .bubbleMenuButton {
+ min-width: 40px;
+ }
+ }
+ }
+ }
+}
diff --git a/src/components/Editor/ImageBubbleMenu/ImageBubbleMenu.tsx b/src/components/Editor/BubbleMenu/FigureBubbleMenu.tsx
similarity index 62%
rename from src/components/Editor/ImageBubbleMenu/ImageBubbleMenu.tsx
rename to src/components/Editor/BubbleMenu/FigureBubbleMenu.tsx
index c6156c68..4ae20add 100644
--- a/src/components/Editor/ImageBubbleMenu/ImageBubbleMenu.tsx
+++ b/src/components/Editor/BubbleMenu/FigureBubbleMenu.tsx
@@ -1,43 +1,40 @@
import type { Editor } from '@tiptap/core'
-import styles from './ImageBubbleMenu.module.scss'
+import styles from './FigureBubbleMenu.module.scss'
import { clsx } from 'clsx'
import { Icon } from '../../_shared/Icon'
+import { useLocalize } from '../../../context/localize'
-type BubbleMenuProps = {
+type Props = {
editor: Editor
- ref: (el: HTMLDivElement) => void
+ ref: (el: HTMLElement) => void
}
-export const ImageBubbleMenu = (props: BubbleMenuProps) => {
+export const FigureBubbleMenu = (props: Props) => {
+ const { t } = useLocalize()
return (
-
diff --git a/src/components/Editor/extensions/Article.ts b/src/components/Editor/extensions/Article.ts
new file mode 100644
index 00000000..15a91511
--- /dev/null
+++ b/src/components/Editor/extensions/Article.ts
@@ -0,0 +1,66 @@
+import { Node, mergeAttributes } from '@tiptap/core'
+
+declare module '@tiptap/core' {
+ interface Commands {
+ Article: {
+ toggleArticle: () => ReturnType
+ setArticleFloat: (float: null | 'left' | 'half-left' | 'right' | 'half-right') => ReturnType
+ setArticleBg: (bg: null | string) => ReturnType
+ }
+ }
+}
+
+export default Node.create({
+ name: 'article',
+
+ defaultOptions: {
+ HTMLAttributes: {
+ 'data-type': 'incut'
+ }
+ },
+ group: 'block',
+ content: 'block+',
+
+ parseHTML() {
+ return [
+ {
+ tag: 'article'
+ }
+ ]
+ },
+
+ renderHTML({ HTMLAttributes }) {
+ return ['article', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes), 0]
+ },
+
+ addAttributes() {
+ return {
+ 'data-float': {
+ default: null
+ },
+ 'data-bg': {
+ default: null
+ }
+ }
+ },
+
+ addCommands() {
+ return {
+ toggleArticle:
+ () =>
+ ({ commands }) => {
+ return commands.toggleWrap('article')
+ },
+ setArticleFloat:
+ (value) =>
+ ({ commands }) => {
+ return commands.updateAttributes(this.name, { 'data-float': value })
+ },
+ setArticleBg:
+ (value) =>
+ ({ commands }) => {
+ return commands.updateAttributes(this.name, { 'data-bg': value })
+ }
+ }
+ }
+})
diff --git a/src/components/Editor/extensions/CustomBlockquote.ts b/src/components/Editor/extensions/CustomBlockquote.ts
new file mode 100644
index 00000000..681b9a29
--- /dev/null
+++ b/src/components/Editor/extensions/CustomBlockquote.ts
@@ -0,0 +1,48 @@
+import { Blockquote } from '@tiptap/extension-blockquote'
+import { Command } from '@tiptap/core'
+
+export type QuoteTypes = 'quote' | 'punchline'
+
+declare module '@tiptap/core' {
+ interface Commands {
+ CustomBlockquote: {
+ toggleBlockquote: (type: QuoteTypes) => ReturnType
+ setBlockQuoteFloat: (float: null | 'left' | 'right') => ReturnType
+ }
+ }
+}
+
+export const CustomBlockquote = Blockquote.extend({
+ name: 'blockquote',
+ defaultOptions: {
+ HTMLAttributes: {},
+ group: 'block',
+ content: 'block+'
+ },
+ addAttributes() {
+ return {
+ 'data-float': {
+ default: null
+ },
+ 'data-type': {
+ default: null
+ }
+ }
+ },
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-ignore
+ addCommands() {
+ return {
+ toggleBlockquote:
+ (type) =>
+ ({ commands }) => {
+ return commands.toggleWrap(this.name, { 'data-type': type })
+ },
+ setBlockQuoteFloat:
+ (value) =>
+ ({ commands }) => {
+ return commands.updateAttributes(this.name, { 'data-float': value })
+ }
+ }
+ }
+})
diff --git a/src/components/Editor/extensions/CustomImage.ts b/src/components/Editor/extensions/CustomImage.ts
index f5d68447..7829e94a 100644
--- a/src/components/Editor/extensions/CustomImage.ts
+++ b/src/components/Editor/extensions/CustomImage.ts
@@ -7,7 +7,7 @@ declare module '@tiptap/core' {
* Add an image
*/
setImage: (options: { src: string; alt?: string; title?: string }) => ReturnType
- setFloat: (float: null | 'left' | 'right') => ReturnType
+ setImageFloat: (float: null | 'left' | 'right') => ReturnType
}
}
}
@@ -42,7 +42,7 @@ export const CustomImage = Image.extend({
attrs: options
})
},
- setFloat:
+ setImageFloat:
(value) =>
({ commands }) => {
return commands.updateAttributes(this.name, { 'data-float': value })