XFA - Add support for overflow element
- and fix few bugs: - avoid infinite loop when layout the document; - avoid confusion between break and layout failure; - don't add margin width in tb layout when getting available space.
This commit is contained in:
parent
246d565e3b
commit
0ea5792c86
@ -146,12 +146,9 @@ function addHTML(node, html, bbox) {
|
|||||||
|
|
||||||
function getAvailableSpace(node) {
|
function getAvailableSpace(node) {
|
||||||
const availableSpace = node[$extra].availableSpace;
|
const availableSpace = node[$extra].availableSpace;
|
||||||
const [marginW, marginH] = node.margin
|
const marginH = node.margin
|
||||||
? [
|
? node.margin.topInset + node.margin.bottomInset
|
||||||
node.margin.leftInset + node.margin.rightInset,
|
: 0;
|
||||||
node.margin.topInset + node.margin.leftInset,
|
|
||||||
]
|
|
||||||
: [0, 0];
|
|
||||||
|
|
||||||
switch (node.layout) {
|
switch (node.layout) {
|
||||||
case "lr-tb":
|
case "lr-tb":
|
||||||
@ -159,36 +156,49 @@ function getAvailableSpace(node) {
|
|||||||
switch (node[$extra].attempt) {
|
switch (node[$extra].attempt) {
|
||||||
case 0:
|
case 0:
|
||||||
return {
|
return {
|
||||||
width: availableSpace.width - marginW - node[$extra].currentWidth,
|
width: availableSpace.width - node[$extra].currentWidth,
|
||||||
height: availableSpace.height - marginH - node[$extra].prevHeight,
|
height: availableSpace.height - marginH - node[$extra].prevHeight,
|
||||||
};
|
};
|
||||||
case 1:
|
case 1:
|
||||||
return {
|
return {
|
||||||
width: availableSpace.width - marginW,
|
width: availableSpace.width,
|
||||||
height: availableSpace.height - marginH - node[$extra].height,
|
height: availableSpace.height - marginH - node[$extra].height,
|
||||||
};
|
};
|
||||||
default:
|
default:
|
||||||
|
// Overflow must stay in the container.
|
||||||
return {
|
return {
|
||||||
width: Infinity,
|
width: Infinity,
|
||||||
height: availableSpace.height - marginH - node[$extra].prevHeight,
|
height: Infinity,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
case "rl-row":
|
case "rl-row":
|
||||||
case "row":
|
case "row":
|
||||||
|
if (node[$extra].attempt === 0) {
|
||||||
const width = node[$extra].columnWidths
|
const width = node[$extra].columnWidths
|
||||||
.slice(node[$extra].currentColumn)
|
.slice(node[$extra].currentColumn)
|
||||||
.reduce((a, x) => a + x);
|
.reduce((a, x) => a + x);
|
||||||
return { width, height: availableSpace.height - marginH };
|
return { width, height: availableSpace.height - marginH };
|
||||||
|
}
|
||||||
|
// Overflow must stay in the container.
|
||||||
|
return { width: Infinity, height: Infinity };
|
||||||
case "table":
|
case "table":
|
||||||
case "tb":
|
case "tb":
|
||||||
|
if (node[$extra].attempt === 0) {
|
||||||
return {
|
return {
|
||||||
width: availableSpace.width - marginW,
|
width: availableSpace.width,
|
||||||
height: availableSpace.height - marginH - node[$extra].height,
|
height: availableSpace.height - marginH - node[$extra].height,
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
// Overflow must stay in the container.
|
||||||
|
return { width: Infinity, height: Infinity };
|
||||||
case "position":
|
case "position":
|
||||||
default:
|
default:
|
||||||
|
if (node[$extra].attempt === 0) {
|
||||||
return availableSpace;
|
return availableSpace;
|
||||||
}
|
}
|
||||||
|
// Overflow must stay in the container.
|
||||||
|
return { width: Infinity, height: Infinity };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export { addHTML, flushHTML, getAvailableSpace };
|
export { addHTML, flushHTML, getAvailableSpace };
|
||||||
|
@ -17,7 +17,6 @@ import {
|
|||||||
$acceptWhitespace,
|
$acceptWhitespace,
|
||||||
$addHTML,
|
$addHTML,
|
||||||
$appendChild,
|
$appendChild,
|
||||||
$break,
|
|
||||||
$childrenToHTML,
|
$childrenToHTML,
|
||||||
$content,
|
$content,
|
||||||
$extra,
|
$extra,
|
||||||
@ -91,6 +90,12 @@ const SVG_NS = "http://www.w3.org/2000/svg";
|
|||||||
// to handle the situation.
|
// to handle the situation.
|
||||||
const MAX_ATTEMPTS_FOR_LRTB_LAYOUT = 2;
|
const MAX_ATTEMPTS_FOR_LRTB_LAYOUT = 2;
|
||||||
|
|
||||||
|
// It's possible to have a bug in the layout and so as
|
||||||
|
// a consequence we could loop for ever in Template::toHTML()
|
||||||
|
// so in order to avoid that (and avoid a OOM crash) we break
|
||||||
|
// the loop after having MAX_EMPTY_PAGES empty pages.
|
||||||
|
const MAX_EMPTY_PAGES = 3;
|
||||||
|
|
||||||
function _setValue(templateNode, value) {
|
function _setValue(templateNode, value) {
|
||||||
if (!templateNode.value) {
|
if (!templateNode.value) {
|
||||||
const nodeValue = new Value({});
|
const nodeValue = new Value({});
|
||||||
@ -194,26 +199,19 @@ const NOTHING = 0;
|
|||||||
const NOSPACE = 1;
|
const NOSPACE = 1;
|
||||||
const VALID = 2;
|
const VALID = 2;
|
||||||
function checkDimensions(node, space) {
|
function checkDimensions(node, space) {
|
||||||
|
if (node[$getParent]().layout === "position") {
|
||||||
|
return VALID;
|
||||||
|
}
|
||||||
const [x, y, w, h] = getTransformedBBox(node);
|
const [x, y, w, h] = getTransformedBBox(node);
|
||||||
if (node.w === 0 || node.h === 0) {
|
if (node.w === 0 || node.h === 0) {
|
||||||
return VALID;
|
return VALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node.w !== "" && Math.round(x + w - space.width) > 1) {
|
if (node.w !== "" && Math.round(x + w - space.width) > 1) {
|
||||||
const area = getRoot(node)[$extra].currentContentArea;
|
|
||||||
if (x + w > area.w) {
|
|
||||||
return NOTHING;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NOSPACE;
|
return NOSPACE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node.h !== "" && Math.round(y + h - space.height) > 1) {
|
if (node.h !== "" && Math.round(y + h - space.height) > 1) {
|
||||||
const area = getRoot(node)[$extra].currentContentArea;
|
|
||||||
if (y + h > area.h) {
|
|
||||||
return NOTHING;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NOSPACE;
|
return NOSPACE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -393,8 +391,7 @@ class Area extends XFAObject {
|
|||||||
availableSpace,
|
availableSpace,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (
|
const result = this[$childrenToHTML]({
|
||||||
!this[$childrenToHTML]({
|
|
||||||
filter: new Set([
|
filter: new Set([
|
||||||
"area",
|
"area",
|
||||||
"draw",
|
"draw",
|
||||||
@ -404,13 +401,16 @@ class Area extends XFAObject {
|
|||||||
"subformSet",
|
"subformSet",
|
||||||
]),
|
]),
|
||||||
include: true,
|
include: true,
|
||||||
})
|
});
|
||||||
) {
|
|
||||||
|
if (!result.success) {
|
||||||
|
if (result.isBreak()) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
// Nothing to propose for the element which doesn't fit the
|
// Nothing to propose for the element which doesn't fit the
|
||||||
// available space.
|
// available space.
|
||||||
delete this[$extra];
|
delete this[$extra];
|
||||||
// TODO: return failure or not ?
|
return HTMLResult.FAILURE;
|
||||||
return HTMLResult.empty;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
style.width = measureToString(this[$extra].width);
|
style.width = measureToString(this[$extra].width);
|
||||||
@ -2121,22 +2121,28 @@ class ExclGroup extends XFAObject {
|
|||||||
this[$extra].attempt < MAX_ATTEMPTS_FOR_LRTB_LAYOUT;
|
this[$extra].attempt < MAX_ATTEMPTS_FOR_LRTB_LAYOUT;
|
||||||
this[$extra].attempt++
|
this[$extra].attempt++
|
||||||
) {
|
) {
|
||||||
if (
|
const result = this[$childrenToHTML]({
|
||||||
this[$childrenToHTML]({
|
|
||||||
filter,
|
filter,
|
||||||
include: true,
|
include: true,
|
||||||
})
|
});
|
||||||
) {
|
if (result.success) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (result.isBreak()) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
failure = this[$extra].attempt === 2;
|
failure = this[$extra].attempt === 2;
|
||||||
} else {
|
} else {
|
||||||
failure = !this[$childrenToHTML]({
|
const result = this[$childrenToHTML]({
|
||||||
filter,
|
filter,
|
||||||
include: true,
|
include: true,
|
||||||
});
|
});
|
||||||
|
failure = !result.success;
|
||||||
|
if (failure && result.isBreak()) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (failure) {
|
if (failure) {
|
||||||
@ -4131,12 +4137,6 @@ class Subform extends XFAObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
[$toHTML](availableSpace) {
|
[$toHTML](availableSpace) {
|
||||||
if (this[$extra] && this[$extra].afterBreakAfter) {
|
|
||||||
const ret = this[$extra].afterBreakAfter;
|
|
||||||
delete this[$extra];
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.presence === "hidden" || this.presence === "inactive") {
|
if (this.presence === "hidden" || this.presence === "inactive") {
|
||||||
return HTMLResult.EMPTY;
|
return HTMLResult.EMPTY;
|
||||||
}
|
}
|
||||||
@ -4152,6 +4152,21 @@ class Subform extends XFAObject {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.breakBefore.children.length >= 1) {
|
||||||
|
const breakBefore = this.breakBefore.children[0];
|
||||||
|
if (!breakBefore[$extra]) {
|
||||||
|
// Set $extra to true to consume it.
|
||||||
|
breakBefore[$extra] = true;
|
||||||
|
return HTMLResult.breakNode(breakBefore);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this[$extra] && this[$extra].afterBreakAfter) {
|
||||||
|
const result = this[$extra].afterBreakAfter;
|
||||||
|
delete this[$extra];
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: incomplete.
|
// TODO: incomplete.
|
||||||
fixDimensions(this);
|
fixDimensions(this);
|
||||||
const children = [];
|
const children = [];
|
||||||
@ -4174,15 +4189,6 @@ class Subform extends XFAObject {
|
|||||||
currentWidth: 0,
|
currentWidth: 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this.breakBefore.children.length >= 1) {
|
|
||||||
const breakBefore = this.breakBefore.children[0];
|
|
||||||
if (!breakBefore[$extra]) {
|
|
||||||
breakBefore[$extra] = true;
|
|
||||||
getRoot(this)[$break](breakBefore);
|
|
||||||
return HTMLResult.FAILURE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (checkDimensions(this, availableSpace)) {
|
switch (checkDimensions(this, availableSpace)) {
|
||||||
case NOTHING:
|
case NOTHING:
|
||||||
return HTMLResult.EMPTY;
|
return HTMLResult.EMPTY;
|
||||||
@ -4192,6 +4198,14 @@ class Subform extends XFAObject {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let noBreakOnOverflow = false;
|
||||||
|
if (this.overflow && this.overflow.target) {
|
||||||
|
const root = getRoot(this);
|
||||||
|
const target = root[$searchNode](this.overflow.target, this);
|
||||||
|
noBreakOnOverflow =
|
||||||
|
target && target[0] === root[$extra].currentContentArea;
|
||||||
|
}
|
||||||
|
|
||||||
const filter = new Set([
|
const filter = new Set([
|
||||||
"area",
|
"area",
|
||||||
"draw",
|
"draw",
|
||||||
@ -4232,32 +4246,32 @@ class Subform extends XFAObject {
|
|||||||
attributes.xfaName = this.name;
|
attributes.xfaName = this.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
let failure;
|
// If the container overflows into itself we add an extra
|
||||||
if (this.layout === "lr-tb" || this.layout === "rl-tb") {
|
// layout step to accept finally the element which caused
|
||||||
for (
|
// the overflow.
|
||||||
;
|
let maxRun =
|
||||||
this[$extra].attempt < MAX_ATTEMPTS_FOR_LRTB_LAYOUT;
|
this.layout === "lr-tb" || this.layout === "rl-tb"
|
||||||
this[$extra].attempt++
|
? MAX_ATTEMPTS_FOR_LRTB_LAYOUT
|
||||||
) {
|
: 1;
|
||||||
if (
|
maxRun += noBreakOnOverflow ? 1 : 0;
|
||||||
this[$childrenToHTML]({
|
for (; this[$extra].attempt < maxRun; this[$extra].attempt++) {
|
||||||
filter,
|
const result = this[$childrenToHTML]({
|
||||||
include: true,
|
|
||||||
})
|
|
||||||
) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
failure = this[$extra].attempt === 2;
|
|
||||||
} else {
|
|
||||||
failure = !this[$childrenToHTML]({
|
|
||||||
filter,
|
filter,
|
||||||
include: true,
|
include: true,
|
||||||
});
|
});
|
||||||
|
if (result.success) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (result.isBreak()) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this[$extra].attempt === maxRun) {
|
||||||
|
if (this.overflow) {
|
||||||
|
getRoot(this)[$extra].overflowNode = this.overflow;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (failure) {
|
|
||||||
if (this.layout === "position") {
|
if (this.layout === "position") {
|
||||||
delete this[$extra];
|
delete this[$extra];
|
||||||
}
|
}
|
||||||
@ -4294,19 +4308,17 @@ class Subform extends XFAObject {
|
|||||||
bbox = [this.x, this.y, width, height];
|
bbox = [this.x, this.y, width, height];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const result = HTMLResult.success(createWrapper(this, html), bbox);
|
||||||
|
|
||||||
if (this.breakAfter.children.length >= 1) {
|
if (this.breakAfter.children.length >= 1) {
|
||||||
const breakAfter = this.breakAfter.children[0];
|
const breakAfter = this.breakAfter.children[0];
|
||||||
getRoot(this)[$break](breakAfter);
|
this[$extra].afterBreakAfter = result;
|
||||||
this[$extra].afterBreakAfter = HTMLResult.success(
|
return HTMLResult.breakNode(breakAfter);
|
||||||
createWrapper(this, html),
|
|
||||||
bbox
|
|
||||||
);
|
|
||||||
return HTMLResult.FAILURE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
delete this[$extra];
|
delete this[$extra];
|
||||||
|
|
||||||
return HTMLResult.success(createWrapper(this, html), bbox);
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4456,10 +4468,6 @@ class Template extends XFAObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[$break](node) {
|
|
||||||
this[$extra].breakingNode = node;
|
|
||||||
}
|
|
||||||
|
|
||||||
[$searchNode](expr, container) {
|
[$searchNode](expr, container) {
|
||||||
if (expr.startsWith("#")) {
|
if (expr.startsWith("#")) {
|
||||||
// This is an id.
|
// This is an id.
|
||||||
@ -4477,7 +4485,7 @@ class Template extends XFAObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this[$extra] = {
|
this[$extra] = {
|
||||||
breakingNode: null,
|
overflowNode: null,
|
||||||
pageNumber: 1,
|
pageNumber: 1,
|
||||||
pagePosition: "first",
|
pagePosition: "first",
|
||||||
oddOrEven: "odd",
|
oddOrEven: "odd",
|
||||||
@ -4540,8 +4548,20 @@ class Template extends XFAObject {
|
|||||||
let targetPageArea;
|
let targetPageArea;
|
||||||
let leader = null;
|
let leader = null;
|
||||||
let trailer = null;
|
let trailer = null;
|
||||||
|
let hasSomething = true;
|
||||||
|
let hasSomethingCounter = 0;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
|
if (!hasSomething) {
|
||||||
|
// Nothing has been added in the previous page
|
||||||
|
if (++hasSomethingCounter === MAX_EMPTY_PAGES) {
|
||||||
|
warn("XFA - Something goes wrong: please file a bug.");
|
||||||
|
return mainHtml;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
hasSomethingCounter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
targetPageArea = null;
|
targetPageArea = null;
|
||||||
const page = pageArea[$toHTML]().html;
|
const page = pageArea[$toHTML]().html;
|
||||||
mainHtml.children.push(page);
|
mainHtml.children.push(page);
|
||||||
@ -4560,6 +4580,17 @@ class Template extends XFAObject {
|
|||||||
const htmlContentAreas = page.children.filter(node =>
|
const htmlContentAreas = page.children.filter(node =>
|
||||||
node.attributes.class.includes("xfaContentarea")
|
node.attributes.class.includes("xfaContentarea")
|
||||||
);
|
);
|
||||||
|
|
||||||
|
hasSomething = false;
|
||||||
|
|
||||||
|
const flush = index => {
|
||||||
|
const html = root[$flushHTML]();
|
||||||
|
if (html) {
|
||||||
|
hasSomething = true;
|
||||||
|
htmlContentAreas[index].children.push(html);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
for (let i = 0, ii = contentAreas.length; i < ii; i++) {
|
for (let i = 0, ii = contentAreas.length; i < ii; i++) {
|
||||||
const contentArea = (this[$extra].currentContentArea = contentAreas[i]);
|
const contentArea = (this[$extra].currentContentArea = contentAreas[i]);
|
||||||
const space = { width: contentArea.w, height: contentArea.h };
|
const space = { width: contentArea.w, height: contentArea.h };
|
||||||
@ -4574,7 +4605,7 @@ class Template extends XFAObject {
|
|||||||
trailer = null;
|
trailer = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
let html = root[$toHTML](space);
|
const html = root[$toHTML](space);
|
||||||
if (html.success) {
|
if (html.success) {
|
||||||
if (html.html) {
|
if (html.html) {
|
||||||
htmlContentAreas[i].children.push(html.html);
|
htmlContentAreas[i].children.push(html.html);
|
||||||
@ -4582,17 +4613,11 @@ class Template extends XFAObject {
|
|||||||
return mainHtml;
|
return mainHtml;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for breakBefore / breakAfter
|
if (html.isBreak()) {
|
||||||
let mustBreak = false;
|
const node = html.breakNode;
|
||||||
if (this[$extra].breakingNode) {
|
|
||||||
const node = this[$extra].breakingNode;
|
|
||||||
this[$extra].breakingNode = null;
|
|
||||||
|
|
||||||
if (node.targetType === "auto") {
|
if (node.targetType === "auto") {
|
||||||
html = root[$flushHTML]();
|
flush(i);
|
||||||
if (html) {
|
|
||||||
htmlContentAreas[i].children.push(html);
|
|
||||||
}
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4616,34 +4641,68 @@ class Template extends XFAObject {
|
|||||||
|
|
||||||
if (node.targetType === "pageArea") {
|
if (node.targetType === "pageArea") {
|
||||||
if (startNew) {
|
if (startNew) {
|
||||||
mustBreak = true;
|
flush(i);
|
||||||
|
i = Infinity;
|
||||||
} else if (target === pageArea || !(target instanceof PageArea)) {
|
} else if (target === pageArea || !(target instanceof PageArea)) {
|
||||||
// Just ignore the break and do layout again.
|
// Just ignore the break and do layout again.
|
||||||
i--;
|
i--;
|
||||||
continue;
|
|
||||||
} else {
|
} else {
|
||||||
// We must stop the contentAreas filling and go to the next page.
|
// We must stop the contentAreas filling and go to the next page.
|
||||||
targetPageArea = target;
|
targetPageArea = target;
|
||||||
mustBreak = true;
|
flush(i);
|
||||||
|
i = Infinity;
|
||||||
}
|
}
|
||||||
} else if (
|
} else if (node.targetType === "contentArea") {
|
||||||
target === "contentArea" ||
|
const index = contentAreas.findIndex(e => e === target);
|
||||||
!(target instanceof ContentArea)
|
if (index !== -1) {
|
||||||
) {
|
flush(i);
|
||||||
// Just ignore the break and do layout again.
|
i = index - 1;
|
||||||
|
} else {
|
||||||
i--;
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this[$extra].overflowNode) {
|
||||||
|
const node = this[$extra].overflowNode;
|
||||||
|
this[$extra].overflowNode = null;
|
||||||
|
|
||||||
|
flush(i);
|
||||||
|
|
||||||
|
if (node.leader) {
|
||||||
|
leader = this[$searchNode](node.leader, node[$getParent]());
|
||||||
|
leader = leader ? leader[0] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
html = root[$flushHTML]();
|
if (node.trailer) {
|
||||||
if (html) {
|
trailer = this[$searchNode](node.trailer, node[$getParent]());
|
||||||
htmlContentAreas[i].children.push(html);
|
trailer = trailer ? trailer[0] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mustBreak) {
|
let target = null;
|
||||||
break;
|
if (node.target) {
|
||||||
|
target = this[$searchNode](node.target, node[$getParent]());
|
||||||
|
target = target ? target[0] : target;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (target instanceof PageArea) {
|
||||||
|
// We must stop the contentAreas filling and go to the next page.
|
||||||
|
targetPageArea = target;
|
||||||
|
i = Infinity;
|
||||||
|
continue;
|
||||||
|
} else if (target instanceof ContentArea) {
|
||||||
|
const index = contentAreas.findIndex(e => e === target);
|
||||||
|
if (index !== -1) {
|
||||||
|
i = index - 1;
|
||||||
|
} else {
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
flush(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
this[$extra].pageNumber += 1;
|
this[$extra].pageNumber += 1;
|
||||||
|
@ -168,21 +168,30 @@ function getBBox(data) {
|
|||||||
|
|
||||||
class HTMLResult {
|
class HTMLResult {
|
||||||
static get FAILURE() {
|
static get FAILURE() {
|
||||||
return shadow(this, "FAILURE", new HTMLResult(false, null, null));
|
return shadow(this, "FAILURE", new HTMLResult(false, null, null, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
static get EMPTY() {
|
static get EMPTY() {
|
||||||
return shadow(this, "EMPTY", new HTMLResult(true, null, null));
|
return shadow(this, "EMPTY", new HTMLResult(true, null, null, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(success, html, bbox) {
|
constructor(success, html, bbox, breakNode) {
|
||||||
this.success = success;
|
this.success = success;
|
||||||
this.html = html;
|
this.html = html;
|
||||||
this.bbox = bbox;
|
this.bbox = bbox;
|
||||||
|
this.breakNode = breakNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
isBreak() {
|
||||||
|
return !!this.breakNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
static breakNode(node) {
|
||||||
|
return new HTMLResult(false, null, null, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
static success(html, bbox = null) {
|
static success(html, bbox = null) {
|
||||||
return new HTMLResult(true, html, bbox);
|
return new HTMLResult(true, html, bbox, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,6 @@ import { searchNode } from "./som.js";
|
|||||||
const $acceptWhitespace = Symbol();
|
const $acceptWhitespace = Symbol();
|
||||||
const $addHTML = Symbol();
|
const $addHTML = Symbol();
|
||||||
const $appendChild = Symbol();
|
const $appendChild = Symbol();
|
||||||
const $break = Symbol();
|
|
||||||
const $childrenToHTML = Symbol();
|
const $childrenToHTML = Symbol();
|
||||||
const $clean = Symbol();
|
const $clean = Symbol();
|
||||||
const $cleanup = Symbol();
|
const $cleanup = Symbol();
|
||||||
@ -342,7 +341,7 @@ class XFAObject {
|
|||||||
const availableSpace = this[$getAvailableSpace]();
|
const availableSpace = this[$getAvailableSpace]();
|
||||||
const res = this[$extra].failingNode[$toHTML](availableSpace);
|
const res = this[$extra].failingNode[$toHTML](availableSpace);
|
||||||
if (!res.success) {
|
if (!res.success) {
|
||||||
return false;
|
return res;
|
||||||
}
|
}
|
||||||
if (res.html) {
|
if (res.html) {
|
||||||
this[$addHTML](res.html, res.bbox);
|
this[$addHTML](res.html, res.bbox);
|
||||||
@ -357,7 +356,7 @@ class XFAObject {
|
|||||||
}
|
}
|
||||||
const res = gen.value;
|
const res = gen.value;
|
||||||
if (!res.success) {
|
if (!res.success) {
|
||||||
return false;
|
return res;
|
||||||
}
|
}
|
||||||
if (res.html) {
|
if (res.html) {
|
||||||
this[$addHTML](res.html, res.bbox);
|
this[$addHTML](res.html, res.bbox);
|
||||||
@ -366,7 +365,7 @@ class XFAObject {
|
|||||||
|
|
||||||
this[$extra].generator = null;
|
this[$extra].generator = null;
|
||||||
|
|
||||||
return true;
|
return HTMLResult.EMPTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
[$setSetAttributes](attributes) {
|
[$setSetAttributes](attributes) {
|
||||||
@ -960,7 +959,6 @@ export {
|
|||||||
$acceptWhitespace,
|
$acceptWhitespace,
|
||||||
$addHTML,
|
$addHTML,
|
||||||
$appendChild,
|
$appendChild,
|
||||||
$break,
|
|
||||||
$childrenToHTML,
|
$childrenToHTML,
|
||||||
$clean,
|
$clean,
|
||||||
$cleanup,
|
$cleanup,
|
||||||
|
1
test/pdfs/xfa_annual_expense_report.pdf.link
Normal file
1
test/pdfs/xfa_annual_expense_report.pdf.link
Normal file
@ -0,0 +1 @@
|
|||||||
|
https://web.archive.org/web/20210509141350/https://www.sos.state.oh.us/globalassets/elections/directives/2020/dir2020-25_annualexpensereport.pdf
|
1
test/pdfs/xfa_annual_voting_survey.pdf.link
Normal file
1
test/pdfs/xfa_annual_voting_survey.pdf.link
Normal file
@ -0,0 +1 @@
|
|||||||
|
https://web.archive.org/web/20210509141345/https://www.sos.state.oh.us/globalassets/elections/directives/2020/dir2020-25_eavsform.pdf
|
1
test/pdfs/xfa_bug1716047.pdf.link
Normal file
1
test/pdfs/xfa_bug1716047.pdf.link
Normal file
@ -0,0 +1 @@
|
|||||||
|
https://bugzilla.mozilla.org/attachment.cgi?id=9226577
|
@ -930,6 +930,30 @@
|
|||||||
"link": true,
|
"link": true,
|
||||||
"type": "load"
|
"type": "load"
|
||||||
},
|
},
|
||||||
|
{ "id": "xfa_bug1716047",
|
||||||
|
"file": "pdfs/xfa_bug1716047.pdf",
|
||||||
|
"md5": "2f524163bd8397f43d195090978c3b56",
|
||||||
|
"link": true,
|
||||||
|
"rounds": 1,
|
||||||
|
"enableXfa": true,
|
||||||
|
"type": "eq"
|
||||||
|
},
|
||||||
|
{ "id": "xfa_annual_expense_report",
|
||||||
|
"file": "pdfs/xfa_annual_expense_report.pdf",
|
||||||
|
"md5": "06866e7a6bbc0346789208ef5f6e885c",
|
||||||
|
"link": true,
|
||||||
|
"rounds": 1,
|
||||||
|
"enableXfa": true,
|
||||||
|
"type": "eq"
|
||||||
|
},
|
||||||
|
{ "id": "xfa_annual_voting_survey",
|
||||||
|
"file": "pdfs/xfa_annual_voting_survey.pdf",
|
||||||
|
"md5": "92239648ea1bf189435c927e498c4ec9",
|
||||||
|
"link": true,
|
||||||
|
"rounds": 1,
|
||||||
|
"enableXfa": true,
|
||||||
|
"type": "eq"
|
||||||
|
},
|
||||||
{ "id": "xfa_fish_licence",
|
{ "id": "xfa_fish_licence",
|
||||||
"file": "pdfs/xfa_fish_licence.pdf",
|
"file": "pdfs/xfa_fish_licence.pdf",
|
||||||
"md5": "9b993128bbd7f4217098fd44116ebec2",
|
"md5": "9b993128bbd7f4217098fd44116ebec2",
|
||||||
|
Loading…
Reference in New Issue
Block a user