Fix portrait image flow and drop-cap spacing
This commit is contained in:
@@ -123,12 +123,6 @@ class LayoutRendererModule extends BaseModule {
|
||||
}
|
||||
});
|
||||
|
||||
// Position words according to layout with proper justification
|
||||
let wordCount = 0;
|
||||
let lastChild = null;
|
||||
let syllable = "";
|
||||
const stack = [paragraph];
|
||||
|
||||
if (layoutData.dropCap && layoutData.dropCapText) {
|
||||
const dropCap = document.createElement('span');
|
||||
dropCap.className = 'drop-cap story-drop-cap';
|
||||
@@ -137,6 +131,26 @@ class LayoutRendererModule extends BaseModule {
|
||||
paragraph.appendChild(dropCap);
|
||||
}
|
||||
|
||||
if (Array.isArray(layoutData.lines) && layoutData.lines.length > 0) {
|
||||
layoutData.lines.forEach((line, lineIndex) => {
|
||||
this.renderLine({
|
||||
paragraph,
|
||||
line,
|
||||
lineIndex,
|
||||
contentTopLines,
|
||||
lineHeight,
|
||||
maxLineWidth
|
||||
});
|
||||
});
|
||||
return paragraph;
|
||||
}
|
||||
|
||||
// Position words according to layout with proper justification
|
||||
let wordCount = 0;
|
||||
let lastChild = null;
|
||||
let syllable = "";
|
||||
const stack = [paragraph];
|
||||
|
||||
for (let i = 1; i < breaks.length; i++) {
|
||||
const lineIndex = i - 1;
|
||||
const lineWidth = measures[Math.min(lineIndex, measures.length - 1)];
|
||||
@@ -277,6 +291,75 @@ class LayoutRendererModule extends BaseModule {
|
||||
return paragraph;
|
||||
}
|
||||
|
||||
renderLine({ paragraph, line, lineIndex, contentTopLines, lineHeight, maxLineWidth }) {
|
||||
const lineWidth = Number(line.measure || maxLineWidth);
|
||||
const lineOffset = Number(line.offset || 0);
|
||||
const ratio = line.isFinal ? 0 : Number(line.ratio || 0);
|
||||
const stack = [paragraph];
|
||||
let currentLeft = 0;
|
||||
let lastChild = null;
|
||||
let syllable = '';
|
||||
|
||||
for (let j = 0; j < line.nodes.length; j += 1) {
|
||||
const node = line.nodes[j];
|
||||
if (!node) continue;
|
||||
|
||||
if (node.type === 'box' && node.value !== '') {
|
||||
const followsGlue = j > 0 && line.nodes[j - 1].type === 'glue';
|
||||
const isTrailingPunctuation = /^[,.;:!?…)]$/.test(node.value) && !followsGlue;
|
||||
|
||||
if (lastChild && isTrailingPunctuation) {
|
||||
syllable += node.value;
|
||||
lastChild.innerHTML = syllable;
|
||||
currentLeft += node.width || 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
const word = document.createElement('span');
|
||||
word.className = ['word', line.styleClass || ''].filter(Boolean).join(' ');
|
||||
word.style.position = 'absolute';
|
||||
word.style.display = 'inline-block';
|
||||
word.style.whiteSpace = 'nowrap';
|
||||
word.dataset.line = String(lineIndex);
|
||||
word.dataset.lineStart = String(lineOffset);
|
||||
word.dataset.lineWidth = String(lineWidth);
|
||||
word.style.top = `${((contentTopLines + lineIndex) * lineHeight * 100) / parseFloat(paragraph.style.height)}%`;
|
||||
word.style.left = `${((lineOffset + currentLeft) * 100) / maxLineWidth}%`;
|
||||
word.style.opacity = '0';
|
||||
word.style.visibility = 'hidden';
|
||||
word.style.clipPath = 'inset(0 100% 0 0)';
|
||||
syllable = node.value;
|
||||
word.innerHTML = syllable;
|
||||
stack[stack.length - 1].appendChild(word);
|
||||
lastChild = word;
|
||||
currentLeft += node.width || 0;
|
||||
} else if (node.type === 'tag') {
|
||||
if (String(node.value || '').startsWith('</')) {
|
||||
if (stack.length > 1) stack.pop();
|
||||
} else {
|
||||
const template = document.createElement('div');
|
||||
template.innerHTML = node.value;
|
||||
const tag = template.firstChild;
|
||||
if (tag) {
|
||||
tag.style.display = 'contents';
|
||||
stack[stack.length - 1].appendChild(tag);
|
||||
stack.push(tag);
|
||||
}
|
||||
}
|
||||
} else if (node.type === 'glue' && node.width !== 0) {
|
||||
let adjustedWidth = node.width || 0;
|
||||
if (ratio > 0) {
|
||||
adjustedWidth += (node.stretch || 0) * ratio;
|
||||
} else if (ratio < 0) {
|
||||
adjustedWidth += (node.shrink || 0) * ratio;
|
||||
}
|
||||
currentLeft += adjustedWidth;
|
||||
} else if (node.type === 'penalty' && node.penalty === 100 && line.hyphenated && j === line.nodes.length - 1 && lastChild) {
|
||||
lastChild.innerHTML = `${lastChild.innerHTML}-`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
measureNaturalLineWidth(nodes, startPosition, endPosition) {
|
||||
let width = 0;
|
||||
for (let j = startPosition; j <= endPosition; j++) {
|
||||
|
||||
Reference in New Issue
Block a user