Forum How do I...?

Cannot make prince-linebreak-magic work

elvanto
I cannot seem to get prince-linebreak-magic to work. I have the following code inside a table cell:

<span class="email">me@myemail.com</span>


And in my CSS:

.email {
	prince-linebreak-magic: auto;
}


But the email address doesn't break and just goes outside the table.

Am I using it wrong?
mikeday
Actually prince-linebreak-magic is "auto" by default, but currently it only breaks at slashes, not at @ characters. We are just adding support for "word-wrap: break-word" which will allow breaking at any point, this will be available shortly. In the meantime, you could use prince-text-replace to add a zero-width space after the @:
.email {
    prince-text-replace: '@' '@\200b'
}
elvanto
Perfect workaround. Can "prince-text-replace" be used twice? It seem to break my code. I was hoping to also apply the same break point for the dot. Any ideas?

.email {
	prince-text-replace: \'@\' \'@\\\200b\';
	prince-text-replace: \'.\' \'.\\\200b\';
}


BTW, you guys are the best! Really really really happy with prince. Coming from TCPDF, your system has saved me hours. The amount of work arounds I had to put in place to make TCPDF was ridiculous.

Thanks for being awesome!
mikeday
Thanks! Glad you like it. :)

You can apply multiple text replacements like this:
prince-text-replace: 'a' 'b' 'c' 'd'

This will replace 'a' with 'b' and 'c' with 'd'. As with all CSS properties, if you repeat the property multiple times then only the last one will be applied (or the one with the most specific selector).
elvanto
That did it! Thanks!
xiaomiao6185
Hi, what if there is no special character to replace? for example, theemailaddresisveryyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyylong@gmail.com I used {price-text-replace: '@', '\200B@'}, but the characters before the "@" sign are still too long to exceed the margin of the table.
mikeday
The latest Prince alpha version supports "word-wrap: break-word" which will allow breaking anywhere within a word if absolutely necessary to avoid overflow.
xiaomiao6185
I actually need "word-break: break-all" to work. Does the alpha version support "word-break: break-all"? Because my characters are like emails/urls which don't have space between it.
mikeday
Yes, the alpha supports the word-break property as well as the word-wrap (aka overflow-wrap) property.
xiaomiao6185
thank you very much!
xiaomiao6185
when are you going to release the alpha version? Thanks!
mikeday
It is usable now, but some other features may be changed or renamed before the final release. There is no date for the final release yet.
sfinktah
There no longer seems anyway to disable "breaking at slashes".

Setting "-prince-line-break-magic: none;" does not appear to disable this feature.

Even with all line breaking disabled, lines that would otherwise overflow right off the page are still broken at /

This makes base64-encoded data look quite messed up :(

Edited by sfinktah

mikeday
The property name is "prince-linebreak-magic", no hyphen between line and break. :)
sfinktah
me <- dumbass.

But now I have a real problem, though it's not a bug in Prince. It's just that it doesn't support `line-break` and have some oddly encoded base64 content that's using hyphens, which I would like to not break at.

line-break: anywhere

Is the only (browser) solution I can find.

Unless I can replace the hyphens with a similar looking unicode symbol, but I'm not sure which ones it would break at.



Edited by sfinktah

mikeday
Applying "overflow-wrap: break-word" perhaps?
sfinktah
Unfortunately not.
mikeday
Ah must be "word-break: break-all" then? I always get those mixed up. Here is an example of three different possibilities:
<p style="border: solid red thin; width: 2in">
fadjhkhdajkfhdjakfhdjkafhdjkahfdjak----fdahjfdlkajhfkdaf---fdahjkfdahjkdfahjkfda
</p>
<p style="border: solid red thin; width: 2in; overflow-wrap: break-word">
fadjhkhdajkfhdjakfhdjkafhdjkahfdjak----fdahjfdlkajhfkdaf---fdahjkfdahjkdfahjkfda
</p>
<p style="border: solid red thin; width: 2in; word-break: break-all">
fadjhkhdajkfhdjakfhdjkafhdjkahfdjak----fdahjfdlkajhfkdaf---fdahjkfdahjkdfahjkfda
</p>
sfinktah
`word-break: break-all` worked, I get them mixed up as-well. I think I may have been testing with `word-wrap`.

Many thanks,

BTW, it seems that it is not very good at calculating line lengths, unless that can be tweaked by -prince-text-wrap?

I tried it with Liberation Mono, it's strange. It seems to be related to either very thin or non-word characters.

Here is an interesting test:



<div style="font-family: Liberation Mono">
	<p style="border: solid red thin; width: 2in; word-break: break-all">
	....................................................................................................
	</p>
	<p style="border: solid red thin; width: 2in; word-break: break-all">
	----------------------------------------------------------------------------------------------------
	</p>
	<p style="border: solid red thin; width: 2in; word-break: break-all">
	MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
	</p>
	<p style="border: solid red thin; width: 2in; word-break: break-all">
	MowerMan9.MowerMan9.MowerMan9.MowerMan9.MowerMan9.MowerMan9.MowerMan9.MowerMan9.MowerMan9.MowerMan9.MowerMan9.MowerMan9.MowerMan9.MowerMan9.MowerMan9.MowerMan9.MowerMan9.MowerMan9.MowerMan9.MowerMan9.MowerMan9.MowerMan9.MowerMan9.MowerMan9.MowerMan9.MowerMan9.MowerMan9.MowerMan9.MowerMan9.MowerMan9.MowerMan9.MowerMan9.MowerMan9.MowerMan9.MowerMan9.MowerMan9.MowerMan9.MowerMan9.MowerMan9.MowerMan9.MowerMan9.MowerMan9.MowerMan9.MowerMan9.MowerMan9.MowerMan9.MowerMan9.MowerMan9.MowerMan9.MowerMan9.
	</p>
</div>


The - and . do not wrap at all, and the MowerMan9's vary by line content.

Edited by sfinktah

csant
The - and . do not wrap at all, and the MowerMan9's vary by line content.


In those cases "overflow-wrap: break-word" does a good job at breaking in a more predictable way.
sfinktah
Nice.. that fixed the non-breaking punctuation (period and hyphen), but did nothing for the MowerMen.

I think that part may actually be a bug, since the results can be described as:
foreach line:
    line_length = line_length - max(non_alpha_chars) + count(non_alpha_chars)


where max is the maximum count across all lines. (in this case, 2)

Edited by sfinktah

mikeday
The word-break property only wants to break within a word, so it will not insert break points before trailing punctuation or after leading punctuation (or in Prince, around any punctuation at all).

I think for the general case of wanting to allow breaks between any pair of characters it might be necessary to insert zero-width space characters using JavaScript (or the prince-text-replace property if you only need to add them around specific characters).
sfinktah
Unfortunately the issue is not that extra breaking needs to be inserted, it's that break is happening prematurely (if I understand your explanation correctly) to avoid have to break on a non-word character. This is probably why line-break: anywhere was my first go-to when doing browser testing.

Looking at the test sample again, I can see it in a different light. It's avoiding (as you say) having punctuation at the start or end of a line.



Even Chrome will do that:



Unless
linbreak: anywhere
is set, which I assume is just a big switch to turn all the line wrapping logic off and just dumbly break only when required.

You must admit the humour though -- so much effort just to emulate the behaviour of what would naturally happen when printing a text file on a line printer in 1991. :)

Edited by sfinktah

mikeday
Yes, it's funny!

However inserting zero-width spaces around the punctuation should have the correct result, for example with this CSS:
prince-text-replace: '.' '\200b.\200b'
sfinktah
That's a handy faux-css feature there, but fortunately this HTML is being written by a python script. 500 pages of sniffed web traffic for a court case. You might have heard of it a while back: https://www.abc.net.au/news/science/2018-11-08/grand-theft-auto-cheat-crackdown-house-raid/10472358

Anyway, with that in mind, you could give me a precise definition of what prince defines as punctuation? Or just paste the relevant C code right into a message so I can get the output picture-perfect :)

mikeday
Currently anything that's not alphanumeric or a mark character, it's quite conservative. If you're dealing with ASCII text then you could just insert a zero-width space after each character.
sfinktah
Did I mention the 500 pages thing? That would be some huge output, but I guess I can do the equivalent of
isprint && !isalnum


Are apostrophes counted? because that css syntax would get wierd

Edited by sfinktah

mikeday
Computers have no difficulty chewing through 500 pages of anything these days!
sfinktah
[removed]

Edited by sfinktah

sfinktah
Woops, no trailing ; .... computer generated output, garbage in, garbage out.
sfinktah

.node > div > div > div > dl > .dd {
    display: inline-block;
    position: relative;
    left: 0;
    width: 30em;
    font-family: "Liberation Mono";
    /* line-break: anywhere; */
    /* -prince-linebreak-magic: none; */
    word-break: break-all;
    overflow-wrap: break-word;
    prince-text-replace: ' ' '\200b \200b';
    prince-text-replace: '!' '\200b!\200b';
    prince-text-replace: '"' '\200b"\200b';
    prince-text-replace: '#' '\200b#\200b';
    prince-text-replace: '$' '\200b$\200b';
    prince-text-replace: '%' '\200b%\200b';
    prince-text-replace: '&' '\200b&\200b';
    prince-text-replace: '(' '\200b(\200b';
    prince-text-replace: ')' '\200b)\200b';
    prince-text-replace: '*' '\200b*\200b';
    prince-text-replace: '+' '\200b+\200b';
    prince-text-replace: ',' '\200b,\200b';
    prince-text-replace: '-' '\200b-\200b';
    prince-text-replace: '.' '\200b.\200b';
    prince-text-replace: '/' '\200b/\200b';
    prince-text-replace: ':' '\200b:\200b';
    prince-text-replace: ';' '\200b;\200b';
    prince-text-replace: '<' '\200b<\200b';
    prince-text-replace: '=' '\200b=\200b';
    prince-text-replace: '>' '\200b>\200b';
    prince-text-replace: '?' '\200b?\200b';
    prince-text-replace: '@' '\200b@\200b';
    prince-text-replace: '[' '\200b[\200b';
    prince-text-replace: ']' '\200b]\200b';
    prince-text-replace: '^' '\200b^\200b';
    prince-text-replace: '_' '\200b_\200b';
    prince-text-replace: '`' '\200b`\200b';
    prince-text-replace: '{' '\200b{\200b';
    prince-text-replace: '|' '\200b|\200b';
    prince-text-replace: '}' '\200b}\200b';
    prince-text-replace: '~' '\200b~\200b';
}

sfinktah
The effect is exacerbated with a non-mono font (and if I was using a mono font, I would just use pre and line feeds anyway).

sfinktah
okay, I got it almost lined in (in mono) by removing all the prince-text-replaces except the three I needed.

    prince-text-replace: '-' '\200b-\200b';
    prince-text-replace: '.' '\200b.\200b';
    prince-text-replace: '=' '\200b=\200b';
    prince-text-replace: '_' '\200b_\200b';


Though the hyphen is still causing issues, probably because it's just a "break here" kind of character. Still fooling around with CSS options.

Seems there might be a limit (2 or 3?) on how many prince-text-replace can be used at once, with the final ones taking precedence over the earlier ones?

Edited by sfinktah

howcome
You can apply multiple text replacements like this:
prince-text-replace: 'a' 'b' 'c' 'd'

This will replace 'a' with 'b' and 'c' with 'd'. As with all CSS properties, if you repeat the property multiple times then only the last one will be applied (or the one with the most specific selector).
sfinktah
Thanks, that actually worked perfectly! It's not even breaking on spaces :)

I'll paste the combined CSS in, though it will be ugly.

It has every character except \ and ' because I didn't want to worry about escaping them.

    word-break: break-all;
    prince-text-replace: '.' '\200b.\200b' '=' '\200b=\200b' ' ' '\200b \200b' '!' '\200b!\200b' '"' '\200b"\200b' '#' '\200b#\200b' '$' '\200b$\200b' '%' '\200b%\200b' '&' '\200b&\200b' '(' '\200b(\200b' ')' '\200b)\200b' '*' '\200b*\200b' '+' '\200b+\200b' ',' '\200b,\200b' '-' '\200b-\200b' '.' '\200b.\200b' '/' '\200b/\200b' ':' '\200b:\200b' '' '\200b;\200b' '<' '\200b<\200b' '=' '\200b=\200b' '>' '\200b>\200b' '?' '\200b?\200b' '@' '\200b@\200b' '[' '\200b[\200b' ']' '\200b]\200b' '^' '\200b^\200b' '_' '\200b_\200b' '`' '\200b`\200b' '{' '\200b{\200b' '|' '\200b|\200b' '}' '\200b}\200b' '~' '\200b~\200b';

Edited by sfinktah