Commit bb440fff authored by Яков's avatar Яков
Browse files

update

parent b5e1ee2c
...@@ -374,9 +374,8 @@ const Iframe = Node.create({ ...@@ -374,9 +374,8 @@ const Iframe = Node.create({
renderHTML({ node, HTMLAttributes }) { renderHTML({ node, HTMLAttributes }) {
const align = node.attrs.align || 'left' const align = node.attrs.align || 'left'
const style = getStyleForAlign(align) // Инлайновых стилей нет: размеры едут атрибутами width/height, раскладку
if (node.attrs.width) style.push(`width: ${node.attrs.width}px`) // задаёт data-align через CSS платформы. Подробности — в Image.jsx.
if (node.attrs.height) style.push(`height: ${node.attrs.height}px`)
return [ return [
'iframe', 'iframe',
...@@ -385,7 +384,8 @@ const Iframe = Node.create({ ...@@ -385,7 +384,8 @@ const Iframe = Node.create({
allow: 'fullscreen', allow: 'fullscreen',
frameborder: node.attrs.frameborder ?? 0, frameborder: node.attrs.frameborder ?? 0,
'data-align': align, 'data-align': align,
style: style.join('; '), width: node.attrs.width || undefined,
height: node.attrs.height || undefined,
}), }),
] ]
}, },
......
...@@ -206,8 +206,17 @@ const ResizableImageTemplate = ({ node, updateAttributes, editor, getPos, select ...@@ -206,8 +206,17 @@ const ResizableImageTemplate = ({ node, updateAttributes, editor, getPos, select
const initImageSize = () => { const initImageSize = () => {
try { 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; isInitialized.current = true;
return; return;
} }
...@@ -243,8 +252,11 @@ const ResizableImageTemplate = ({ node, updateAttributes, editor, getPos, select ...@@ -243,8 +252,11 @@ const ResizableImageTemplate = ({ node, updateAttributes, editor, getPos, select
}; };
const handleLoad = () => { const handleLoad = () => {
// Если размеры уже заданы в атрибутах, пропускаем инициализацию // Достаточно одной ширины — высота выводится из пропорций.
if (node.attrs.width && node.attrs.height) { // Условие «width && height» пропускало картинки, у которых сохранён
// только width (в боевой базе таких большинство: 305 уроков против 79),
// и они получали натуральный размер вместо авторского. См. initImageSize.
if (node.attrs.width) {
isInitialized.current = true; isInitialized.current = true;
return; return;
} }
...@@ -378,9 +390,17 @@ const ResizableImageTemplate = ({ node, updateAttributes, editor, getPos, select ...@@ -378,9 +390,17 @@ const ResizableImageTemplate = ({ node, updateAttributes, editor, getPos, select
}; };
// Внешняя обёртка (NodeViewWrapper): управляет float/block-layout и отступами // Внешняя обёртка (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 getOuterStyle = () => {
const { align, wrap, width } = node.attrs; 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 sharedMargin = { marginTop: '0.5rem', marginBottom: '0.5rem' };
const noSelect = { userSelect: 'none', WebkitUserSelect: 'none', touchAction: 'manipulation' }; const noSelect = { userSelect: 'none', WebkitUserSelect: 'none', touchAction: 'manipulation' };
...@@ -415,7 +435,7 @@ const ResizableImageTemplate = ({ node, updateAttributes, editor, getPos, select ...@@ -415,7 +435,7 @@ const ResizableImageTemplate = ({ node, updateAttributes, editor, getPos, select
// Внутренний контейнер: всегда inline-block — надёжно получает высоту от дочернего img // Внутренний контейнер: всегда inline-block — надёжно получает высоту от дочернего img
const getInnerStyle = () => { const getInnerStyle = () => {
const { align, width } = node.attrs; const { align, width } = node.attrs;
const w = width ? `${width}px` : 'auto'; const w = width ? `min(${width}px, 100%)` : 'auto';
const base = { const base = {
position: 'relative', position: 'relative',
display: 'inline-block', display: 'inline-block',
...@@ -429,7 +449,7 @@ const ResizableImageTemplate = ({ node, updateAttributes, editor, getPos, select ...@@ -429,7 +449,7 @@ const ResizableImageTemplate = ({ node, updateAttributes, editor, getPos, select
}; };
if (align === 'center') { if (align === 'center') {
return { ...base, display: 'block', marginLeft: 'auto', marginRight: 'auto', return { ...base, display: 'block', marginLeft: 'auto', marginRight: 'auto',
width: width ? `${width}px` : 'fit-content' }; width: width ? `min(${width}px, 100%)` : 'fit-content' };
} }
return base; return base;
}; };
...@@ -446,7 +466,7 @@ const ResizableImageTemplate = ({ node, updateAttributes, editor, getPos, select ...@@ -446,7 +466,7 @@ const ResizableImageTemplate = ({ node, updateAttributes, editor, getPos, select
// Стили для самого изображения // Стили для самого изображения
const getImageStyle = () => ({ const getImageStyle = () => ({
width: node.attrs.width ? `${node.attrs.width}px` : 'auto', width: node.attrs.width ? `min(${node.attrs.width}px, 100%)` : 'auto',
height: 'auto', height: 'auto',
maxWidth: '100%', maxWidth: '100%',
display: 'block', display: 'block',
...@@ -745,23 +765,17 @@ const ResizableImageExtension = TipTapImage.extend({ ...@@ -745,23 +765,17 @@ const ResizableImageExtension = TipTapImage.extend({
const align = node.attrs.align || 'left'; const align = node.attrs.align || 'left';
const wrap = node.attrs.wrap || false; const wrap = node.attrs.wrap || false;
const style = []; // Инлайновых стилей здесь БОЛЬШЕ НЕТ — намеренно.
//
if (align === 'center') { // Раньше сюда писались 'width: 640px; height: 480px; float: left'. Из-за
style.push('display: block', 'margin-left: auto', 'margin-right: auto'); // пиксельной высоты картинка искажалась при сужении окна (замерено 26% на
} else if (align === 'left') { // 768 px и 42% на 600 px), а перебить инлайн из таблицы стилей можно было
wrap // только через !important.
? style.push('float: left', 'margin-right: 1rem') //
: style.push('display: block', 'margin-right: auto'); // Теперь размеры едут обычными атрибутами width/height: браузер выводит из
} else if (align === 'right') { // них соотношение сторон, и height: auto в CSS работает без искажений.
wrap // Раскладку задают data-align и data-wrap — правила в
? style.push('float: right', 'margin-left: 1rem') // AtmaGuru/src/React/sass/_content.scss. См. §6.1 ТЗ.
: style.push('display: block', 'margin-left: auto');
}
if (width) style.push(`width: ${width}px`);
if (height) style.push(`height: ${height}px`);
return [ return [
'img', 'img',
{ {
...@@ -771,7 +785,7 @@ const ResizableImageExtension = TipTapImage.extend({ ...@@ -771,7 +785,7 @@ const ResizableImageExtension = TipTapImage.extend({
width, width,
height, height,
'data-align': align, 'data-align': align,
style: style.join('; '), ...(wrap ? { 'data-wrap': 'true' } : {}),
...rest, ...rest,
} }
]; ];
......
...@@ -703,29 +703,15 @@ export const InteractiveImage = Node.create({ ...@@ -703,29 +703,15 @@ export const InteractiveImage = Node.create({
const align = node.attrs.align || 'left'; const align = node.attrs.align || 'left';
const wrap = node.attrs.wrap || false; const wrap = node.attrs.wrap || false;
const points = node.attrs.points || []; 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 [ return [
'interactive-image', 'interactive-image',
{ {
src, src,
width, width,
height, height,
style: style.join('; '),
'data-align': align, 'data-align': align,
'data-wrap': wrap ? 'true' : undefined, 'data-wrap': wrap ? 'true' : undefined,
'data-points': JSON.stringify(points), 'data-points': JSON.stringify(points),
......
...@@ -376,16 +376,16 @@ const Video = Node.create({ ...@@ -376,16 +376,16 @@ const Video = Node.create({
renderHTML({ node, HTMLAttributes }) { renderHTML({ node, HTMLAttributes }) {
const align = node.attrs.align || 'left' const align = node.attrs.align || 'left'
const style = getStyleForAlign(align) // Инлайновых стилей нет: размеры едут атрибутами width/height, раскладку
if (node.attrs.width) style.push(`width: ${node.attrs.width}px`) // задаёт data-align через CSS платформы. Подробности — в Image.jsx.
if (node.attrs.height) style.push(`height: ${node.attrs.height}px`)
return [ return [
'video', 'video',
mergeAttributes(HTMLAttributes, { mergeAttributes(HTMLAttributes, {
controls: node.attrs.controls !== false ? 1 : null, controls: node.attrs.controls !== false ? 1 : null,
'data-align': align, 'data-align': align,
style: style.join('; '), width: node.attrs.width || undefined,
height: node.attrs.height || undefined,
}), }),
] ]
}, },
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment