How can I add a watermark to a PDF that is generated by puppeteer? - node.js

I'm using puppeteer to generate a PDF file for my report view and I want to add a watermark on that report PDF version. Is there anyway that I can do that?

The easiest way to do it, is to add an additional element to the page, which represents the watermark when the PDF is created. As you can change the page in any way you like, you could add a "Watermark" element to the page like this:
await page.evaluate(() => {
const div = document.createElement('div');
div.innerHTML = 'Watermark Text...';
div.style.cssText = "position: fixed; bottom: 10px; right: 10px; background: red; z-index: 10000";
document.body.appendChild(div);
});
await page.pdf(/* ... */);
The code adds a fixed element to the bottom right of the page. When printed it will appear on every printed page. You can use any kind of CSS styling to style your watermark. Just make sure it has a high z-index value, so that nothing overlaps it.

Related

Azure Maps - Map is not opening at the correct size

I have a page with azure maps, and most of the time it loads normally and the map covers the entire screen. But at some points when refreshing the page, the map is limited to a small size, and if I just refresh the screen or even open the browser console, the size is updated correctly.
<body>
<div id="mapDiv"></div>
</body>
I even created an event in an attempt to make a resize
map.events.add('ready', function () {
setTimeout(function () {
map.map.resize();
}, 1000);
});
Error
enter image description here
when i refresh or open da console
enter image description here
If it is meant to be full screen, make sure to set the width/height to 100% for not only the map, but the html and body tags as well. When you don't specify any styles for the map div, it inherits from it's parents. Try adding this CSS to your page:
html, body, #mapDiv {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}

"Unknown props" warning on console when attaching additional props

I'm using Styled Components v2.1.1.
The documentation says that to avoid unnecessary wrappers we can use the .attrs constructor. See: https://www.styled-components.com/docs/basics#attaching-additional-props
I've tried to use it but I always receive the following warning in the console:
Warning: Unknown props `margin`, `padding` on <input> tag. Remove these props from the element. For details, see (removed )
in input (created by styled.input)
in styled.input (created by InputContainer)
in div (created by InputContainer)
in InputContainer
I've created a Webpack Bin to show the error: https://www.webpackbin.com/bins/-KpKbVG-Ed0jysHeFVVY
Am I using it in the wrong way or is there an issue?
As it seems, the example provided on the styled components website is not an actual usable example.
Since the attrs function creates attributes for the properties you set, the error is correct in saying that the html <input> tag does not support the attributes margin and padding: MDN - HTML input attributes
The error you're seeing was marked as an issue on the styled-components GitHub.
The actual solution is not to literally use the example given in the styled-components documentation. For the full explanation, please refer to the issue report.
The code example given by one of the contributers on Github is to modify the example as follows:
const getSize = p => p.size || '1em'
const Input = styled.input.attrs({
// we can define static props
type: 'password'
})`
color: palevioletred;
font-size: 1em;
border: 2px solid palevioletred;
border-radius: 3px;
/* here we use the dynamically computed props */
margin: ${getSize};
padding: ${getSize};
`;

Calculate text width in pixels server-side

I'm trying to use the following code on my server to estimate the length of some text fields and potentially trim them before sending them by email...
String.prototype.visualLength = function()
{
var element = document.createElement("span");
element.css({
"visibility": "hidden",
"white-space": "nowrap",
"font-weight": "normal",
"font-size": "18px",
"line-height": "40px",
"font-family": "Helvetica, Arial, sans-serif",
"text-decoration": "none"
});
document.body.appendChild(element);
element.innerHTML = this;
return element.offsetWidth;
};
String.prototype.trimToPx = function(length)
{
var tmp = this;
var trimmed = this;
if (tmp.visualLength() > length)
{
trimmed += "...";
while (trimmed.visualLength() > length)
{
tmp = tmp.substring(0, tmp.length-1);
trimmed = tmp + "...";
}
};
return trimmed;
};
Obviously I'm getting an error because "document" is not defined server-side. I added the Meteor packages htmljs and domutils hoping they might solve this, but in vain. And I can't add the Node.js package jsdom because apparently it won't work in deployed Meteor apps.
Any idea how to achieve what I'm trying to do?
You cannot truly rely what will happen on client-side. Even Ubuntu and Windows shows the fonts different because of different hinting, antialiasing and they may have an effect on the displayed sizes.
If you modify your span's css as following, when it has a text larger than the desired space, no matter what, the remaining will be displayed as ...
max-width: 10%;
border: 1px #000 solid; // JUST TO SEE the effect clearly
width: 10%;
overflow: hidden;
height: 20px;
text-overflow: ellipsis;
display: block;
white-space: nowrap;
** Please note that you need a proper height value, other wise the text will go to bottom and what you want will not be achieved.
Try on http://jsfiddle.net/sG6H2/
I don't think this is possible. Server-side code running in node.js does not run in the context of a web browser's rendering environment and so can't access the browser's DOM and available fonts and display configuration. Even if you were to successfully run your code and compute a number, that computation has no relationship to my device when I receive your email. The fonts, the display size and resolution (could be a desktop, could be a mobile device), my own configuration (for example I set a minimum font size in Firefox on my desktop), etc. Instead try defining your size in em units instead of pixels.

sharepoint branding : page width size due to _spBodyOnLoadWrapper() function

i'm trying to make up a different look and feel on my sharepoint site. I try to make my main content's width down to 960px under my form tag in sharepoitn designer. when I refresh the page at the first it renders the main content down to 960px but when the page fishished loading the main content stretches itself to the whole screen's width.
I found out that it's because of the onload script running in body tag. but I caanot remove this script because this work has side effects on page functionality.
the function is _spBodyOnLoadWrapper().
does anyone know this function ? or does anyone know how to come up with this problem ?
UPDATE #1:
My css code is as follows.. I added this class to the main Form on master page:
.mainContent
{
width: 960px;
height:100% !important;
min-height:100% !important;
padding-top: 10px;
margin-left: auto;
margin-right: auto;
direction:rtl;
}
UPDATE #2:
I use v4.master template.
I have taken the ribbon out of the form tag. it's directly after body tag. because I wanted the ribbon to be streched at the top. but when i add this line of code
<body onload="if (typeof(_spBodyOnLoadWrapper) != 'undefined') _spBodyOnLoadWrapper();">
the mainContent blows up. something at the header streches in the whole width and some panels at bottom remains 960px.
you got me interested so I recreated your issue. By default, the javascript will try to inline the width based on its calculations.
However, what you need is to set the class s4-notsetwidth on a wrapping container.
Here is what i did to fix your issue
Add this to the head
<style type="text/css">
#s4-bodyContainer {
width: 960px;
height:100% !important;
min-height:100% !important;
padding-top: 10px;
margin-left: auto;
margin-right: auto;
}
/* Aligns the Top Bars */
.ms-cui-ribbonTopBars {
width: 960px!important;
margin-left:auto;
margin-right:auto;
}
/* Turns off the border on the bottom of the tabs */
.ms-cui-ribbonTopBars > div {
border-bottom:1px solid transparent !important;
}
</style>
Then locate the s4-workspace (that's the immediate parent of #s4-bodyContainer and add class s4-nosetwidth. That should work for you.
Use these two references to achieve exactly what you want (not sure if you want ribbon aligned or not), Randy Drisgill post and Tom Wilson's post.

Isolating CSS for Chrome extension

I'm building a Chrome extension that does some UI injection using content scripts. The problem is that since every website is different and may try to screw around with the default positioning of certain elements (divs, lists) etc, my ui looks different depending on which page it is being used.
I've tried using YUI reset v3 and that helped but didn't remove all the weirdness. Does anybody know of an even more aggressive reset method that does more than just clearing margin/padding and reset text sizes?
Thanks in advance.
We've had a similar issue, we've tried CSS resets and also using specific id tags for the elements and CSS rules, but it was never robust enough...
The best solution was to inject the elements into the DOM as Shadow DOM elements that contain the style inline. You can read your CSS file via AJAX requests and inject them to the Shadow DOM dynamically, just make sure that they are within the web_accessible_resources files (you can use a wildcard to your CSS folder).
In case that you are not familiar with Shadow DOM, here is a good example of how it works. It might take a bit of re-factoring on your end, but it's really the only solution that works a 100%.
I recently created Boundary, a CSS+JS library to solve problems just like this. Boundary creates elements that are completely separate from the existing webpage's CSS.
Take creating a dialog for example. After installing Boundary, you can do this in your content script
var dialog = Boundary.createBox("yourDialogID", "yourDialogClassName");
Boundary.loadBoxCSS("#yourDialogID", "style-for-elems-in-dialog.css");
Boundary.appendToBox(
"#yourDialogID",
"<button id='submit_button'>submit</button>"
);
Boundary.find("#submit_button").click(function() {
// find() function returns a regular jQuery DOM element
// so you can do whatever you want with it.
// some js after button is clicked.
});
Elements within #yourDialogID will not be affected by the existing webpage.
Hope this helps. Please let me know if you have any question.
https://github.com/liviavinci/Boundary
meyerweb's reset styles look slightly more aggressive.
/* http://meyerweb.com/eric/tools/css/reset/
v2.0 | 20110126
License: none (public domain)
*/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
body {
line-height: 1;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
That is why you should inject at document_end. You can do that by setting "run_at": "document_end" in the Content Script Manifest

Resources