Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
lib
react-ag-qeditor
Commits
bb440fff
Commit
bb440fff
authored
Aug 28, 2026
by
Яков
Browse files
update
parent
b5e1ee2c
Changes
4
Hide whitespace changes
Inline
Side-by-side
src/extensions/Iframe.js
View file @
bb440fff
...
...
@@ -374,9 +374,8 @@ const Iframe = Node.create({
renderHTML
({
node
,
HTMLAttributes
})
{
const
align
=
node
.
attrs
.
align
||
'
left
'
const
style
=
getStyleForAlign
(
align
)
if
(
node
.
attrs
.
width
)
style
.
push
(
`width:
${
node
.
attrs
.
width
}
px`
)
if
(
node
.
attrs
.
height
)
style
.
push
(
`height:
${
node
.
attrs
.
height
}
px`
)
// Инлайновых стилей нет: размеры едут атрибутами width/height, раскладку
// задаёт data-align через CSS платформы. Подробности — в Image.jsx.
return
[
'
iframe
'
,
...
...
@@ -385,7 +384,8 @@ const Iframe = Node.create({
allow
:
'
fullscreen
'
,
frameborder
:
node
.
attrs
.
frameborder
??
0
,
'
data-align
'
:
align
,
style
:
style
.
join
(
'
;
'
),
width
:
node
.
attrs
.
width
||
undefined
,
height
:
node
.
attrs
.
height
||
undefined
,
}),
]
},
...
...
src/extensions/Image.jsx
View file @
bb440fff
...
...
@@ -206,8 +206,17 @@ const ResizableImageTemplate = ({ node, updateAttributes, editor, getPos, select
const
initImageSize
=
()
=>
{
try
{
// Если размеры уже заданы в атрибутах - используем их сразу
if
(
node
.
attrs
.
width
&&
node
.
attrs
.
height
)
{
// Ширина задана автором — уважаем её и ничего не пересчитываем.
//
// Раньше проверялись ОБЕ величины (width && height). Но в сохранённых
// уроках height есть далеко не всегда: по боевой базе width="N" стоит
// в 305 уроках, а height — в 79. Для остальных условие не срабатывало,
// и картинка при открытии урока молча получала натуральный размер
// вместо авторского: в базе width="1000", в редакторе 80 px.
// Дальше это уезжало в базу при первом же сохранении.
//
// Высота не нужна: она выводится из пропорций (height: auto).
if
(
node
.
attrs
.
width
)
{
isInitialized
.
current
=
true
;
return
;
}
...
...
@@ -243,8 +252,11 @@ const ResizableImageTemplate = ({ node, updateAttributes, editor, getPos, select
};
const
handleLoad
=
()
=>
{
// Если размеры уже заданы в атрибутах, пропускаем инициализацию
if
(
node
.
attrs
.
width
&&
node
.
attrs
.
height
)
{
// Достаточно одной ширины — высота выводится из пропорций.
// Условие «width && height» пропускало картинки, у которых сохранён
// только width (в боевой базе таких большинство: 305 уроков против 79),
// и они получали натуральный размер вместо авторского. См. initImageSize.
if
(
node
.
attrs
.
width
)
{
isInitialized
.
current
=
true
;
return
;
}
...
...
@@ -378,9 +390,17 @@ const ResizableImageTemplate = ({ node, updateAttributes, editor, getPos, select
};
// Внешняя обёртка (NodeViewWrapper): управляет float/block-layout и отступами
// width: min(Npx, 100%) вместо Npx — намеренно.
//
// Фиксированная пиксельная ширина на обёртке делает её минимально-содержимым
// блоком: в узком контейнере (ячейка таблицы) она не даёт ячейке ужаться,
// и таблица растягивается — замерено 1495 px внутри контейнера на 832 px.
// У учащегося тот же <img> с max-width: 100% спокойно ужимается до 229 px,
// и вид расходится. min() сохраняет ширину, заданную автором, и при этом
// позволяет сжаться. Проверяется docs/stand/media-parity.js.
const
getOuterStyle
=
()
=>
{
const
{
align
,
wrap
,
width
}
=
node
.
attrs
;
const
w
=
width
?
`
${
width
}
px`
:
'
auto
'
;
const
w
=
width
?
`
min(
${
width
}
px
, 100%)
`
:
'
auto
'
;
const
sharedMargin
=
{
marginTop
:
'
0.5rem
'
,
marginBottom
:
'
0.5rem
'
};
const
noSelect
=
{
userSelect
:
'
none
'
,
WebkitUserSelect
:
'
none
'
,
touchAction
:
'
manipulation
'
};
...
...
@@ -415,7 +435,7 @@ const ResizableImageTemplate = ({ node, updateAttributes, editor, getPos, select
// Внутренний контейнер: всегда inline-block — надёжно получает высоту от дочернего img
const
getInnerStyle
=
()
=>
{
const
{
align
,
width
}
=
node
.
attrs
;
const
w
=
width
?
`
${
width
}
px`
:
'
auto
'
;
const
w
=
width
?
`
min(
${
width
}
px
, 100%)
`
:
'
auto
'
;
const
base
=
{
position
:
'
relative
'
,
display
:
'
inline-block
'
,
...
...
@@ -429,7 +449,7 @@ const ResizableImageTemplate = ({ node, updateAttributes, editor, getPos, select
};
if
(
align
===
'
center
'
)
{
return
{
...
base
,
display
:
'
block
'
,
marginLeft
:
'
auto
'
,
marginRight
:
'
auto
'
,
width
:
width
?
`
${
width
}
px`
:
'
fit-content
'
};
width
:
width
?
`
min(
${
width
}
px
, 100%)
`
:
'
fit-content
'
};
}
return
base
;
};
...
...
@@ -446,7 +466,7 @@ const ResizableImageTemplate = ({ node, updateAttributes, editor, getPos, select
// Стили для самого изображения
const
getImageStyle
=
()
=>
({
width
:
node
.
attrs
.
width
?
`
${
node
.
attrs
.
width
}
px`
:
'
auto
'
,
width
:
node
.
attrs
.
width
?
`
min(
${
node
.
attrs
.
width
}
px
, 100%)
`
:
'
auto
'
,
height
:
'
auto
'
,
maxWidth
:
'
100%
'
,
display
:
'
block
'
,
...
...
@@ -745,23 +765,17 @@ const ResizableImageExtension = TipTapImage.extend({
const
align
=
node
.
attrs
.
align
||
'
left
'
;
const
wrap
=
node
.
attrs
.
wrap
||
false
;
const
style
=
[];
if
(
align
===
'
center
'
)
{
style
.
push
(
'
display: block
'
,
'
margin-left: auto
'
,
'
margin-right: auto
'
);
}
else
if
(
align
===
'
left
'
)
{
wrap
?
style
.
push
(
'
float: left
'
,
'
margin-right: 1rem
'
)
:
style
.
push
(
'
display: block
'
,
'
margin-right: auto
'
);
}
else
if
(
align
===
'
right
'
)
{
wrap
?
style
.
push
(
'
float: right
'
,
'
margin-left: 1rem
'
)
:
style
.
push
(
'
display: block
'
,
'
margin-left: auto
'
);
}
if
(
width
)
style
.
push
(
`width:
${
width
}
px`
);
if
(
height
)
style
.
push
(
`height:
${
height
}
px`
);
// Инлайновых стилей здесь БОЛЬШЕ НЕТ — намеренно.
//
// Раньше сюда писались 'width: 640px; height: 480px; float: left'. Из-за
// пиксельной высоты картинка искажалась при сужении окна (замерено 26% на
// 768 px и 42% на 600 px), а перебить инлайн из таблицы стилей можно было
// только через !important.
//
// Теперь размеры едут обычными атрибутами width/height: браузер выводит из
// них соотношение сторон, и height: auto в CSS работает без искажений.
// Раскладку задают data-align и data-wrap — правила в
// AtmaGuru/src/React/sass/_content.scss. См. §6.1 ТЗ.
return
[
'
img
'
,
{
...
...
@@ -771,7 +785,7 @@ const ResizableImageExtension = TipTapImage.extend({
width
,
height
,
'
data-align
'
:
align
,
style
:
style
.
join
(
'
;
'
),
...(
wrap
?
{
'
data-wrap
'
:
'
true
'
}
:
{}
),
...
rest
,
}
];
...
...
src/extensions/InteractiveImage.js
View file @
bb440fff
...
...
@@ -703,29 +703,15 @@ export const InteractiveImage = Node.create({
const
align
=
node
.
attrs
.
align
||
'
left
'
;
const
wrap
=
node
.
attrs
.
wrap
||
false
;
const
points
=
node
.
attrs
.
points
||
[];
const
style
=
[];
if
(
align
===
'
center
'
)
{
style
.
push
(
'
display: block
'
,
'
margin-left: auto
'
,
'
margin-right: auto
'
);
}
else
if
(
align
===
'
left
'
)
{
wrap
?
style
.
push
(
'
float: left
'
,
'
margin-right: 1rem
'
)
:
style
.
push
(
'
display: block
'
,
'
margin-right: auto
'
);
}
else
if
(
align
===
'
right
'
)
{
wrap
?
style
.
push
(
'
float: right
'
,
'
margin-left: 1rem
'
)
:
style
.
push
(
'
display: block
'
,
'
margin-left: auto
'
);
}
if
(
width
)
style
.
push
(
`width:
${
width
}
px`
,
'
max-width: 100%
'
);
// Инлайновых стилей нет: размеры едут атрибутами, раскладку задают
// data-align/data-wrap через CSS платформы. Подробности — в Image.jsx.
return
[
'
interactive-image
'
,
{
src
,
width
,
height
,
style
:
style
.
join
(
'
;
'
),
'
data-align
'
:
align
,
'
data-wrap
'
:
wrap
?
'
true
'
:
undefined
,
'
data-points
'
:
JSON
.
stringify
(
points
),
...
...
src/extensions/Video.js
View file @
bb440fff
...
...
@@ -376,16 +376,16 @@ const Video = Node.create({
renderHTML
({
node
,
HTMLAttributes
})
{
const
align
=
node
.
attrs
.
align
||
'
left
'
const
style
=
getStyleForAlign
(
align
)
if
(
node
.
attrs
.
width
)
style
.
push
(
`width:
${
node
.
attrs
.
width
}
px`
)
if
(
node
.
attrs
.
height
)
style
.
push
(
`height:
${
node
.
attrs
.
height
}
px`
)
// Инлайновых стилей нет: размеры едут атрибутами width/height, раскладку
// задаёт data-align через CSS платформы. Подробности — в Image.jsx.
return
[
'
video
'
,
mergeAttributes
(
HTMLAttributes
,
{
controls
:
node
.
attrs
.
controls
!==
false
?
1
:
null
,
'
data-align
'
:
align
,
style
:
style
.
join
(
'
;
'
),
width
:
node
.
attrs
.
width
||
undefined
,
height
:
node
.
attrs
.
height
||
undefined
,
}),
]
},
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment