tc39 / tc39/ecmarkup

Minification flattens Prince's @prince-overlay inside @page, breaking printable output

Open
#729 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
245
Forks
80
Avg merge
10h 46m
Merged PRs (30d)
2

Description

Summary

Since output minification was added (25.0.0; 24.0.0 has no lib/minify.js), an inline <style> containing Prince's @prince-overlay page-region rule is rewritten by clean-css into a plain @page rule. The overlay's declarations — including font-size: 200pt — end up applied to the page itself, which pushes the @top-left / @top-right header image out of the top margin and over the body text, and the overlay is lost.

css/print.css ships this exact rule commented out with "Uncomment when producing WIP versions of final standards", so it's the documented way to get a DRAFT watermark in --printable builds — and it can't work with minification on.

Reproduction

Spec <style> (copied from the commented block in css/print.css):

@page {
  @prince-overlay {
    color: rgba(0,0,0,0.15);
    content: "DRAFT";
    font-family: Arial;
    font-weight: bolder;
    font-size: 200pt;
    transform: rotate(-60deg);
  }
}

ecmarkup spec.html --printable --assets external out/index.html emits:

@page{content:"DRAFT";font-family:Arial;font-weight:bolder;font-size:200pt;transform:rotate(-60deg)}

Standalone, with the clean-css that ecmarkup bundles (5.3.3), at both level: 1 and level: 2:

const CleanCSS = require('clean-css');
new CleanCSS({ level: 2 }).minify(
  '@page { @prince-overlay { content: "DRAFT"; font-size: 200pt } }'
).styles
// => '@page{content:"DRAFT";font-size:200pt}'

Standard page-margin boxes (@top-left etc.) are preserved — it's the vendor at-rule that gets flattened.

Effect in Prince (20240705 for Books, via js/print.js)

Measured on an A4 body page (margin-top: 28mm):

header image body text starts
minified 27–39 mm 45 mm — header overlaps body
--no-minify 10–19 mm 29 mm

No DRAFT overlay in the minified case.

Real-world instance: Ecma-TC54/ECMA-xxx-TEA (ecmarkup 25.0.0) — every page of the CI PDF had the header over the text; working around it with --no-minify on the printable build.

Suggested fixes (any of)

  • Skip CSS minification (or minification entirely) when --printable is set — that HTML only exists to be fed to Prince, so there's nothing to gain.
  • Configure clean-css to leave unknown at-rules alone (e.g. via level: { 1: { specialComments... } } / compatibility, or pre-extract @page blocks and reinsert them untouched).
  • At minimum, note in css/print.css next to the @prince-overlay block that --no-minify is required.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with lib/minify.js and the printable path in js/print.js, then compare the minified output with the CSS block documented in css/print.css. Reproduce the clean-css transformation from the issue and verify that a printable build preserves @prince-overlay, page-margin boxes, and the expected header and body layout.

Written by the indexing model from the issue text.

Assessment

Tech stack
css, typescript
Domain
build-system, cli
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.