nehan
Version:
Html layout engine for paged-media written in Typescript
116 lines • 3.66 kB
JavaScript
import { Utils, Display, WhiteSpace, } from "./public-api";
let collapse_skip_tags = [
"a",
"(text)",
"::before",
"::after",
"br",
"ruby",
"rp",
"rb",
"rt",
"b",
"strong",
];
export class MarginCollapse {
static collapse(element) {
if (!this.isTarget(element)) {
return;
}
let before = Utils.atoi(element.computedStyle.getPropertyValue("margin-before") || "0px");
let prev_max = this.getMaxAfterOfBefore(element);
let new_before = (prev_max >= before) ? 0 : before - prev_max;
element.computedStyle.setProperty("margin-before", String(new_before) + "px");
let after = Utils.atoi(element.computedStyle.getPropertyValue("margin-after") || "0px");
let parent_max = this.getMaxAfterOfParent(element);
let new_after = (parent_max >= after) ? 0 : after - parent_max;
element.computedStyle.setProperty("margin-after", String(new_after) + "px");
}
static hasBorder(element, dir) {
let prop = "border-" + dir + "-width";
let value = element.computedStyle.getPropertyValue(prop) || "0px";
let size = Utils.atoi(value);
return size > 0;
}
static getMaxAfterOfBefore(element) {
if (this.hasBorder(element, "before")) {
return 0;
}
let prev = element.previousSibling, max = 0;
while (prev) {
if (WhiteSpace.isWhiteSpaceElement(prev)) {
prev = prev.previousSibling;
continue;
}
if (!this.isTarget(prev) || this.hasBorder(prev, "after")) {
break;
}
let size = Utils.atoi(prev.computedStyle.getPropertyValue("margin-after") || "0px");
if (size > max) {
max = size;
}
prev = prev.lastChild;
if (!prev) {
break;
}
}
return max;
}
static getMaxAfterOfParent(element) {
if (this.hasBorder(element, "after")) {
return 0;
}
let parent = element.parent, max = 0;
if (!parent || parent.lastChild !== element) {
return 0;
}
while (parent) {
if (!this.isTarget(parent)) {
break;
}
let size = Utils.atoi(parent.computedStyle.getPropertyValue("margin-after") || "0px");
if (size > max) {
max = size;
}
if (!parent.parent) {
break;
}
let last = parent.parent.lastChild;
if (last === null) {
break;
}
while (WhiteSpace.isWhiteSpaceElement(last)) {
last = last.previousSibling;
if (last === null) {
break;
}
}
if (parent !== last) {
break;
}
parent = parent.parent;
}
return max;
}
static isTarget(element) {
if (element.parent === null) {
return false;
}
if (element.isTextElement()) {
return false;
}
if (collapse_skip_tags.indexOf(element.tagName) >= 0) {
return false;
}
let float = element.computedStyle.getPropertyValue("float") || "none";
if (float !== "none") {
return false;
}
let display = Display.load(element);
if (display.isBlockLevel() === false) {
return false;
}
return true;
}
}
//# sourceMappingURL=margin-collapse.js.map