counter-reset: page #93

Open
hejsan opened this Issue May 23, 2013 · 11 comments

Comments

7 participants
@hejsan

hejsan commented May 23, 2013

Is there a plan to support counter-reset?

I have to generate a pdf combined of a lot of reports for different students. Each report needs to have individual page numbers, i.e. not 1/117 thru 117/117 but instead each one would have numbers relative to just that one report, more like 1/5 thru 5/5 and so on.

So optimally counter-reset: page; should reset the counter to 1 and also make the counter(pages) evaluate correctly the number of pages since the last reset.

Is that even doable?

As a backup plan, do you know of any commandline tool to merge multiple pdf's into one that installs on centos?

Thanks for a superb tool btw.

@SimonSapin

This comment has been minimized.

Show comment
Hide comment
@SimonSapin

SimonSapin May 24, 2013

Member

Hi. In this case I’d recommend using the low-level API to render multiple document separately, then write them to a single PDF file. Something like this:

documents = [HTML(string=render_template(student)).render() for student in students]
documents[0].copy([page for doc in documents for page in doc.pages]).write_pdf(target)
Member

SimonSapin commented May 24, 2013

Hi. In this case I’d recommend using the low-level API to render multiple document separately, then write them to a single PDF file. Something like this:

documents = [HTML(string=render_template(student)).render() for student in students]
documents[0].copy([page for doc in documents for page in doc.pages]).write_pdf(target)
@SimonSapin

This comment has been minimized.

Show comment
Hide comment
@SimonSapin

SimonSapin May 24, 2013

Member

Note: PDFtk can also concatenate PDF files, but that’s probably less efficient than the above as it’s just doing more work.

Member

SimonSapin commented May 24, 2013

Note: PDFtk can also concatenate PDF files, but that’s probably less efficient than the above as it’s just doing more work.

@hejsan

This comment has been minimized.

Show comment
Hide comment
@hejsan

hejsan May 24, 2013

Thanks.
Yes I guess this is the only hack free way.
I'm guessing if named pages were supported I could generate one @page for
each student to allow for different headers and footers, but the page
counter would still give me problems.

As this must be a common requirement, to generate multiple documents in a
batch, is this a feature you'd be interested in having in weasyprint?

Thanks again.
On 24 May 2013 05:00, "Simon Sapin" notifications@github.com wrote:

Note: PDFtk http://www.pdflabs.com/docs/pdftk-cli-examples/ can also
concatenate PDF files, but that’s probably less efficient than the above as
it’s just doing more work.


Reply to this email directly or view it on GitHubhttps://github.com/Kozea/WeasyPrint/issues/93#issuecomment-18386661
.

hejsan commented May 24, 2013

Thanks.
Yes I guess this is the only hack free way.
I'm guessing if named pages were supported I could generate one @page for
each student to allow for different headers and footers, but the page
counter would still give me problems.

As this must be a common requirement, to generate multiple documents in a
batch, is this a feature you'd be interested in having in weasyprint?

Thanks again.
On 24 May 2013 05:00, "Simon Sapin" notifications@github.com wrote:

Note: PDFtk http://www.pdflabs.com/docs/pdftk-cli-examples/ can also
concatenate PDF files, but that’s probably less efficient than the above as
it’s just doing more work.


Reply to this email directly or view it on GitHubhttps://github.com/Kozea/WeasyPrint/issues/93#issuecomment-18386661
.

@SimonSapin

This comment has been minimized.

Show comment
Hide comment
@SimonSapin

SimonSapin May 24, 2013

Member

Even with named page, you’d still need more CSS features (like a new page selector) to only reset the page counter on the first page for a given student.

The low-level API (separating the layout into pages form the painting and PDF writing) was designed for this kind thing, and is already supported. What feature do you mean exactly?

Member

SimonSapin commented May 24, 2013

Even with named page, you’d still need more CSS features (like a new page selector) to only reset the page counter on the first page for a given student.

The low-level API (separating the layout into pages form the painting and PDF writing) was designed for this kind thing, and is already supported. What feature do you mean exactly?

@hejsan

This comment has been minimized.

Show comment
Hide comment
@hejsan

hejsan May 24, 2013

Hi, sorry to be unclear.

I may have misunderstood the css page standard (http://dev.w3.org/csswg/css-page/#page-based-counters)

I thought I could simply wrap each "subreport" like this:

<div class="student-report">
 ... report content ... 
</div>
<div class="student-report">
 ... report content ... 
</div>
...

and in the css I'd write:

@page {
    bottom-center {
        content: counter(page)/counter(pages);
    }
}
.student-report {
    counter-reset: page;
    page-break-after: always;
}

And this would have the effect that each student-report would have it's own page numbers and page count.

hejsan commented May 24, 2013

Hi, sorry to be unclear.

I may have misunderstood the css page standard (http://dev.w3.org/csswg/css-page/#page-based-counters)

I thought I could simply wrap each "subreport" like this:

<div class="student-report">
 ... report content ... 
</div>
<div class="student-report">
 ... report content ... 
</div>
...

and in the css I'd write:

@page {
    bottom-center {
        content: counter(page)/counter(pages);
    }
}
.student-report {
    counter-reset: page;
    page-break-after: always;
}

And this would have the effect that each student-report would have it's own page numbers and page count.

@SimonSapin

This comment has been minimized.

Show comment
Hide comment
@SimonSapin

SimonSapin May 24, 2013

Member

I find the spec a bit unclear on this point, but I’m told that this wouldn’t work because of the scoping rules. Your explicit counter-reset would create one scope, and the implicit increment in @page would be a new scope, so that you actually have two page counters.

Maybe we should fix the spec to allow this use case.

Member

SimonSapin commented May 24, 2013

I find the spec a bit unclear on this point, but I’m told that this wouldn’t work because of the scoping rules. Your explicit counter-reset would create one scope, and the implicit increment in @page would be a new scope, so that you actually have two page counters.

Maybe we should fix the spec to allow this use case.

@ktross

This comment has been minimized.

Show comment
Hide comment
@ktross

ktross Dec 17, 2014

I would love to see this supported in WeasyPrint. The only html to pdf renderer I have found that supports this is PrinceXML. Below is an example document that should have 5 total pages with 2 separate counters each having 3 and 2 total pages. Here is a pdf that I generated using the html below.

<!doctype html>
<html>
<head>
    <style>
    div.section {
        counter-reset:page 1 pages 1;
    }
    div.page {
        page-break-after:always;
    }
    @page {
        @top-center {
            content: "Page " counter(page) " of " counter(pages);
        }
    }
    </style>
</head>
<body>
    <div class="section">
        <div class="page">
            this should be page 1/3
        </div>
        <div class="page">
            this should be page 2/3
        </div>
        <div class="page">
            this should be page 3/3
        </div>
    </div>
    <div class="section">
        <div class="page">
            this should be page 1/2
        </div>
        <div class="page">
            this should be page 2/2
        </div>
    </div>
</body>
</html>

ktross commented Dec 17, 2014

I would love to see this supported in WeasyPrint. The only html to pdf renderer I have found that supports this is PrinceXML. Below is an example document that should have 5 total pages with 2 separate counters each having 3 and 2 total pages. Here is a pdf that I generated using the html below.

<!doctype html>
<html>
<head>
    <style>
    div.section {
        counter-reset:page 1 pages 1;
    }
    div.page {
        page-break-after:always;
    }
    @page {
        @top-center {
            content: "Page " counter(page) " of " counter(pages);
        }
    }
    </style>
</head>
<body>
    <div class="section">
        <div class="page">
            this should be page 1/3
        </div>
        <div class="page">
            this should be page 2/3
        </div>
        <div class="page">
            this should be page 3/3
        </div>
    </div>
    <div class="section">
        <div class="page">
            this should be page 1/2
        </div>
        <div class="page">
            this should be page 2/2
        </div>
    </div>
</body>
</html>
@marine-dj

This comment has been minimized.

Show comment
Hide comment
@marine-dj

marine-dj Aug 19, 2015

It would be really sweet if weasyprint could use counter-reset at all - so far I'm surprised to see just how much can actually be done, and this seems to be the only immediate drawback. :)

It would be really sweet if weasyprint could use counter-reset at all - so far I'm surprised to see just how much can actually be done, and this seems to be the only immediate drawback. :)

@rpzk

This comment has been minimized.

Show comment
Hide comment
@rpzk

rpzk Sep 25, 2016

Hello! Could you please clarity this code to me and point me to more productive direction?
"""
documents = [HTML(string=render_template(student)).render() for student in students]
documents[0].copy([page for doc in documents for page in doc.pages]).write_pdf(target)
"""
Because I need to throw a pdf with several pages, with different orientations, backgrounds and sizes.
This is a fragment of my code:

paginas = []
if orientacoes['orientacoes']:
    orientacoes_template = loader.get_template("impressos/receitas/orientacoes.html")
    orientacoes_html = orientacoes_template.render(RequestContext(request, dict(contexto.items() + orientacoes.items())))
    orientacoes_pdf = HTML(string=orientacoes_html).render()
    paginas.append(orientacoes_pdf)
if estadual['estadual']:
    estadual_template = loader.get_template("impressos/receitas/estadual.html")
    estadual_html = estadual_template.render(RequestContext(request, dict(contexto.items() + estadual.items())))
    estadual_pdf = HTML(string=estadual_html).render()
    paginas.append(estadual_pdf)
paginas[0].copy([pagina for p in paginas for pagina in p.pages]).write_pdf('teste.pdf')
return HttpResponse(paginas, content_type='application/pdf')

Thanks a lot for your knowledge and time.

rpzk commented Sep 25, 2016

Hello! Could you please clarity this code to me and point me to more productive direction?
"""
documents = [HTML(string=render_template(student)).render() for student in students]
documents[0].copy([page for doc in documents for page in doc.pages]).write_pdf(target)
"""
Because I need to throw a pdf with several pages, with different orientations, backgrounds and sizes.
This is a fragment of my code:

paginas = []
if orientacoes['orientacoes']:
    orientacoes_template = loader.get_template("impressos/receitas/orientacoes.html")
    orientacoes_html = orientacoes_template.render(RequestContext(request, dict(contexto.items() + orientacoes.items())))
    orientacoes_pdf = HTML(string=orientacoes_html).render()
    paginas.append(orientacoes_pdf)
if estadual['estadual']:
    estadual_template = loader.get_template("impressos/receitas/estadual.html")
    estadual_html = estadual_template.render(RequestContext(request, dict(contexto.items() + estadual.items())))
    estadual_pdf = HTML(string=estadual_html).render()
    paginas.append(estadual_pdf)
paginas[0].copy([pagina for p in paginas for pagina in p.pages]).write_pdf('teste.pdf')
return HttpResponse(paginas, content_type='application/pdf')

Thanks a lot for your knowledge and time.

@Tontyna

This comment has been minimized.

Show comment
Hide comment
@Tontyna

Tontyna Jan 24, 2018

Contributor

The PrinceXML example provided by @ktross is desirable and plausible but doesn't conform to the spec. Quoting section 7.1:

Additionally, a counter named ‘pages’ is automatically created by the UA. Its value is always the total number of pages in the document. (In continuous media this is always 1.) The value of ‘pages’ cannot be manipulated: while ‘counter-reset’ and ‘counter-increment’ statements that set it are valid, they have no effect.

An immutable pages counter in combination with a changeable page counter? Sounds ill-conceived -- but that's what the spec says.

Contributor

Tontyna commented Jan 24, 2018

The PrinceXML example provided by @ktross is desirable and plausible but doesn't conform to the spec. Quoting section 7.1:

Additionally, a counter named ‘pages’ is automatically created by the UA. Its value is always the total number of pages in the document. (In continuous media this is always 1.) The value of ‘pages’ cannot be manipulated: while ‘counter-reset’ and ‘counter-increment’ statements that set it are valid, they have no effect.

An immutable pages counter in combination with a changeable page counter? Sounds ill-conceived -- but that's what the spec says.

@Tontyna Tontyna referenced this issue May 1, 2018

Merged

Handle target-* #604

@danfitz36

This comment has been minimized.

Show comment
Hide comment
@danfitz36

danfitz36 May 16, 2018

named pages and custom counters would allow for separate page numbers per section, but is there a way to get the total pages per section?

named pages and custom counters would allow for separate page numbers per section, but is there a way to get the total pages per section?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment