Как получить все вычисленные свойства CSS элемента и его потомков в Javascript - PullRequest
0 голосов
/ 04 декабря 2018

Я пытаюсь настроить службу в python, используя pdfKit для создания pdf-файла из html-файлов.

Поэтому в основном я отправлю свой элемент в виде строки и ожидаю, что сервер вернет pdfего версия, но для точного представления мне также нужно отправить файл CSS элемента.

Как я могу это сделать?Генерация JSON / объекта только с соответствующими свойствами стиля и селекторами элемента и всех его дочерних элементов.Уважение иерархии и без дубликатов.Есть похожие вопросы, но они устарели и, как правило, не учитывают дочерние элементы.

Я подумал, может быть, есть способ создать новый DOM из этого элемента и затем получить корневой css?

Ответы [ 2 ]

0 голосов
/ 13 декабря 2018

	
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>

Вы можете использовать метод getComputedStyle, чтобы получить вычисленное значение свойства стиля

0 голосов
/ 11 декабря 2018

Вот кое-что, что я придумал: в основном, передайте элемент, из которого вы хотите извлечь стили и его дочерние элементы, и он вернет вам таблицу стилей в виде строки.Перед запуском фрагмента откройте консоль, и вы увидите выходные данные из console.log.

. Поскольку я хотел поддерживать извлечение всех элементов, даже тех, у которых нет селектора, мне пришлось заменить каждый идентификатор элемента науникальный uuid, специально сгенерированный для них, чтобы облегчить стилизацию вашего вывода.Проблема с этим подходом в том случае, если вы используете идентификаторы для стилизации или для взаимодействия с пользователем, вы потеряете такую ​​функциональность на соответствующих элементах после вызова extractCSS.

Однако использовать тривиальноoldId Я перехожу, чтобы измениться, как только ваш pdfKit процесс завершит генерацию.Просто вызовите swapBackIds, передав elements, возвращаемое функцией.Вы можете увидеть разницу в поведении, если вы раскомментируете вызов в моем фрагменте: розовый фон #root исчезнет, ​​потому что стилизация нацелена на элемент id.

В общем, вам нужно:

  1. Позвоните extractCSS с элементом, который вы хотите извлечь
  2. Создайте свой PDF, используя res.stylesheet
  3. Позвоните swapBackIds с 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>
...