J'essaie de configurer un service en python en utilisant pdfKit
pour créer un fichier pdf à partir de fichiers html.
Donc, fondamentalement, j'enverrai mon élément sous forme de chaîne et je m'attendrai à ce que le serveur retourne une version pdf de celle-ci, mais pour être une représentation précise, je dois également envoyer un fichier CSS de l'élément.
Comment puis-je faire ceci? Générez JSON/object avec uniquement les propriétés de style et les sélecteurs d’un élément et de tous ses enfants. Respecter la hiérarchie et pas de doublons. Il existe des questions similaires, mais elles sont dépassées et ont tendance à ne pas prendre en compte les éléments enfants.
Je pensais qu'il y avait peut-être un moyen de créer un nouveau DOM à partir de cet élément, puis d'obtenir le css racine?
Voici quelque chose que je suis venu avec, passe essentiellement l'élément que vous souhaitez extraire les styles et ceux de ses enfants, et il vous retournera la feuille de style sous la forme d'une chaîne. Ouvrez votre console avant d'exécuter l'extrait et vous verrez le résultat du console.log
.
Parce que je voulais supporter l'extraction de chaque élément, même ceux sans sélecteur, je devais remplacer chaque identifiant d'élément par un uuid unique généré spécifiquement pour eux afin de faciliter le style de votre sortie. Le problème avec cette approche est que si vous utilisez des identifiants pour le style ou pour l’interaction de l’utilisateur, vous allez perdre cette fonctionnalité sur les éléments concernés après avoir appelé extractCSS
.
Cependant, il est assez simple d’utiliser la variable oldId
que je passe pour changer une fois que votre processus pdfKit
a terminé la génération. Appelez simplement swapBackIds
en passant la elements
renvoyée par la fonction. Vous pouvez voir la différence de comportement si vous supprimez la mise en commentaire de l'appel dans mon extrait: le fond rose #root
disparaîtrait car le style cible un élément id
.
Dans l'ensemble, vous devez:
extractCSS
avec l'élément que vous voulez extraireres.stylesheet
swapBackIds
avec res.elements
// Generate an unique id for your element
// From https://stackoverflow.com/a/2117523/2054072
function uuidv4 () {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
// Flatten an array
// https://stackoverflow.com/a/15030117/2054072
function flatten(arr) {
return arr.reduce(function (flat, toFlatten) {
return flat.concat(Array.isArray(toFlatten) ? flatten(toFlatten) : toFlatten);
}, []);
}
function recursiveExtract (element) {
var id = uuidv4()
var oldId = element.id
var computed = window.getComputedStyle(element)
var style = computed.cssText
// Now that we get the style, we can swap the id
element.setAttribute('id', id)
// The children are not a real array but a NodeList, we need to convert them
// so we can map over them easily
var children = Array.prototype.slice.call(element.children)
return [{ id: id, style: style, oldId: oldId }].concat(children.map(recursiveExtract))
}
function extractCSS (element) {
if (!element) { return { elements: [], stylesheet: '' } }
var raw = recursiveExtract(element)
var flat = flatten(raw)
return {
elements: flat,
stylesheet: flat.reduce(function (acc, cur) {
var style = '#' + cur.id + ' {\n' + cur.style + '\n}\n\n'
return acc + style
}, '')
}
}
var pdfElement = document.querySelector('#root')
var res = extractCSS(pdfElement)
console.log(res.stylesheet)
function swapBackIds (elements) {
elements.forEach(function (e) {
var element = document.getElementById(e.id)
element.setAttribute('id', e.oldId)
})
}
swapBackIds(res.elements)
#root {
background-color: pink;
}
.style-from-class {
background-color: red;
width: 200px;
height: 200px;
}
.style-from-id {
background-color: green;
width: 100px;
height: 100px;
}
<div id="root">
<span>normal</span>
<span style="background: blue">inline</span>
<div class="style-from-class">
style-class
</div>
<div class="style-from-id">
style-id
<div style="font-size: 10px">a very nested</div>
<div style="font-size: 12px; color: white">and another</div>
</div>
</div>
<div id="ignored-sibling">
</div>
let para = document.querySelector('p');
let compStyles = window.getComputedStyle(para);
para.textContent = 'My computed font-size is ' + compStyles.getPropertyValue('font-size') + ',\nand my computed background is ' + compStyles.getPropertyValue('background') + '.';
p {
width: 400px;
margin: 0 auto;
padding: 20px;
font: 2rem/2 sans-serif;
text-align: center;
background: purple;
color: white;
}
<p>Hello</p>
vous pouvez utiliser la méthode getComputedStyle
pour obtenir la valeur calculée de la propriété de style