Skip to content

Commit

Permalink
test dynamic-images
Browse files Browse the repository at this point in the history
  • Loading branch information
mskec committed Jan 5, 2024
1 parent 9f7a2df commit ab1f28a
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 34 deletions.
4 changes: 1 addition & 3 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@ env:
NODE: 14

on:
pull_request:
branches:
- master
push:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
Expand Down
19 changes: 14 additions & 5 deletions packages/layout/src/node/createInstances.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { castArray } from '@react-pdf/fns';
import { TextInstance } from '@react-pdf/primitives';
import { TextInstance, Image } from '@react-pdf/primitives';
import fetchImage from '../image/fetchImage';

const isString = value => typeof value === 'string';

const isNumber = value => typeof value === 'number';

const isImage = value => value.type === Image;

const isFragment = value =>
value && value.type === Symbol.for('react.fragment');

Expand All @@ -16,7 +19,7 @@ const isFragment = value =>
* @param {Object} React element
* @returns {Array} parsed react elements
*/
const createInstances = element => {
const createInstances = async element => {
if (!element) return [];

if (isString(element) || isNumber(element)) {
Expand All @@ -40,10 +43,16 @@ const createInstances = element => {
props: { style = {}, children = [], ...props },
} = element;

const nextChildren = castArray(children).reduce(
(acc, child) => acc.concat(createInstances(child)),
[],
if (isImage(element)) {
const node = { props, type, style, box: {} };
await fetchImage(node);
return [node];
}

const instances = await Promise.all(
castArray(children).map(child => createInstances(child)),
);
const nextChildren = instances.flat();

return [
{
Expand Down
67 changes: 41 additions & 26 deletions packages/layout/src/steps/resolvePagination.js
Original file line number Diff line number Diff line change
Expand Up @@ -147,44 +147,51 @@ const shouldResolveDynamicNodes = node => {
return isDynamic(node) || children.some(shouldResolveDynamicNodes);
};

const resolveDynamicNodes = (props, node) => {
const resolveDynamicNodes = async (props, node) => {
const isNodeDynamic = isDynamic(node);

// Call render prop on dynamic nodes and append result to children
const resolveChildren = (children = []) => {
const resolveChildren = async (children = []) => {
if (isNodeDynamic) {
const res = node.props.render(props);
return createInstances(res)
.filter(Boolean)
.map(n => resolveDynamicNodes(props, n));
const dynamicRenderResult = node.props.render(props);
const dynamicInstances = await createInstances(dynamicRenderResult);
const resolvedDynamicNodes = await Promise.all(
dynamicInstances
.filter(Boolean)
.map(n => resolveDynamicNodes(props, n)),
);
return resolvedDynamicNodes;
}

return children.map(c => resolveDynamicNodes(props, c));
const resolvedChildren = await Promise.all(
children.map(c => resolveDynamicNodes(props, c)),
);
return resolvedChildren;
};

// We reset dynamic text box so it can be computed again later on
const resetHeight = isNodeDynamic && isText(node);
const box = resetHeight ? { ...node.box, height: 0 } : node.box;

const children = resolveChildren(node.children);
const children = await resolveChildren(node.children);
const lines = isNodeDynamic ? null : node.lines;

return Object.assign({}, node, { box, lines, children });
};

const resolveDynamicPage = (props, page, fontStore) => {
const resolveDynamicPage = async (props, page, fontStore) => {
if (shouldResolveDynamicNodes(page)) {
const resolvedPage = resolveDynamicNodes(props, page);
const resolvedPage = await resolveDynamicNodes(props, page);
return relayoutPage(resolvedPage, fontStore);
}

return page;
};

const splitPage = (page, pageNumber, fontStore) => {
const splitPage = async (page, pageNumber, fontStore) => {
const wrapArea = getWrapArea(page);
const contentArea = getContentArea(page);
const dynamicPage = resolveDynamicPage({ pageNumber }, page, fontStore);
const dynamicPage = await resolveDynamicPage({ pageNumber }, page, fontStore);
const height = page.style.height;

const [currentChilds, nextChilds] = splitNodes(
Expand Down Expand Up @@ -217,7 +224,7 @@ const splitPage = (page, pageNumber, fontStore) => {
return [currentPage, nextPage];
};

const resolvePageIndices = (fontStore, page, pageNumber, pages) => {
const resolvePageIndices = async (fontStore, page, pageNumber, pages) => {
const totalPages = pages.length;

const props = {
Expand All @@ -242,18 +249,23 @@ const dissocSubPageData = page => {
return omit(['subPageNumber', 'subPageTotalPages'], page);
};

const paginate = (page, pageNumber, fontStore) => {
const paginate = async (page, pageNumber, fontStore) => {
if (!page) return [];

if (page.props?.wrap === false) return [page];

let splittedPage = splitPage(page, pageNumber, fontStore);
let splittedPage = await splitPage(page, pageNumber, fontStore);

const pages = [splittedPage[0]];
let nextPage = splittedPage[1];

while (nextPage !== null) {
splittedPage = splitPage(nextPage, pageNumber + pages.length, fontStore);
// eslint-disable-next-line no-await-in-loop
splittedPage = await splitPage(
nextPage,
pageNumber + pages.length,
fontStore,
);

pages.push(splittedPage[0]);
nextPage = splittedPage[1];
Expand All @@ -270,24 +282,27 @@ const paginate = (page, pageNumber, fontStore) => {
* @param {Object} fontStore font store
* @returns {Object} layout node
*/
const resolvePagination = (doc, fontStore) => {
const resolvePagination = async (doc, fontStore) => {
let pages = [];
let pageNumber = 1;

for (let i = 0; i < doc.children.length; i += 1) {
const page = doc.children[i];
let subpages = paginate(page, pageNumber, fontStore);

// eslint-disable-next-line no-restricted-syntax
for (const page of doc.children) {
// eslint-disable-next-line no-await-in-loop
let subpages = await paginate(page, pageNumber, fontStore);
subpages = assocSubPageData(subpages);
pageNumber += subpages.length;
pages = pages.concat(subpages);
}

pages = pages.map((...args) =>
dissocSubPageData(resolvePageIndices(fontStore, ...args)),
);

return assingChildren(pages, doc);
const nextPages = [];
// eslint-disable-next-line no-restricted-syntax
for (const [index, page] of pages.entries()) {
// eslint-disable-next-line no-await-in-loop
const indices = await resolvePageIndices(fontStore, page, index, pages);
nextPages.push(dissocSubPageData(indices));
}
return assingChildren(nextPages, doc);
};

export default resolvePagination;

0 comments on commit ab1f28a

Please sign in to comment.