You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
103 lines
2.8 KiB
JavaScript
103 lines
2.8 KiB
JavaScript
'use strict';
|
|
|
|
const parser = require("../parser");
|
|
const findAlignment = require("../parser/find-alignment");
|
|
const generateStyle = require("../parser/generate-style");
|
|
const measureText = require("../render/measure-text");
|
|
const adjustLineHeights = require("./adjust-line-heights");
|
|
|
|
const sum = require("../util/sum");
|
|
const min = require("../util/min");
|
|
const max = require("../util/max");
|
|
|
|
module.exports = function layoutFormattedText(text, options) {
|
|
if (options.tags === true) {
|
|
let lines = parser(text).map((lineItems) => {
|
|
let measuredItems = lineItems.map((item) => {
|
|
let generatedStyle = generateStyle(item, {
|
|
classes: options.classes,
|
|
defaultStyle: options.defaultStyle
|
|
});
|
|
|
|
return Object.assign({
|
|
measurements: measureText(item.text, generatedStyle),
|
|
style: generatedStyle
|
|
}, item);
|
|
});
|
|
|
|
return {
|
|
alignment: (lineItems.length > 0) ? findAlignment(lineItems[0]) : null,
|
|
items: measuredItems,
|
|
height: max(measuredItems.map(item => item.measurements.height)),
|
|
width: sum(measuredItems.map(item => item.measurements.width)),
|
|
minAscender: min(measuredItems.map(item => item.measurements.ascender)),
|
|
maxDescender: max(measuredItems.map(item => item.measurements.descender))
|
|
}
|
|
});
|
|
|
|
let adjustedLineHeights = adjustLineHeights(lines, options.lineHeight);
|
|
|
|
let currentLineOffset = 0;
|
|
let currentComponentOffset = 0;
|
|
|
|
let positionedItems = lines.reduce((items, line, i) => {
|
|
let newItems = items.concat(line.items.map((item) => {
|
|
let positionedItem = Object.assign({
|
|
x: currentComponentOffset,
|
|
y: currentLineOffset - line.minAscender
|
|
}, item);
|
|
|
|
currentComponentOffset += item.measurements.width;
|
|
return positionedItem;
|
|
}));
|
|
|
|
currentLineOffset += adjustedLineHeights[i];
|
|
currentComponentOffset = 0;
|
|
|
|
return newItems;
|
|
}, []);
|
|
|
|
return {
|
|
width: Math.ceil(max(lines.map(line => line.width))),
|
|
height: Math.ceil(sum(adjustedLineHeights)),
|
|
items: positionedItems
|
|
}
|
|
} else {
|
|
let lines = text.split("\n").map((line) => {
|
|
return {
|
|
text: line,
|
|
measurements: measureText(line, options.defaultStyle)
|
|
};
|
|
});
|
|
|
|
let adjustedLineHeights = adjustLineHeights(lines.map((line) => {
|
|
return {
|
|
text: line.text,
|
|
height: line.measurements.height
|
|
}
|
|
}), options.lineHeight);
|
|
|
|
let currentLineOffset = 0;
|
|
|
|
let positionedItems = lines.map((line, i) => {
|
|
let newItem = {
|
|
text: line.text,
|
|
measurements: line.measurements,
|
|
style: options.defaultStyle,
|
|
x: 0,
|
|
y: currentLineOffset - line.measurements.ascender
|
|
}
|
|
|
|
currentLineOffset += adjustedLineHeights[i];
|
|
|
|
return newItem;
|
|
});
|
|
|
|
return {
|
|
width: Math.ceil(max(lines.map(line => line.measurements.width))),
|
|
height: Math.ceil(sum(adjustedLineHeights)),
|
|
items: positionedItems
|
|
}
|
|
}
|
|
};
|