'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 } } };