如何导出包含所有 CSS 内联的 HTML,就像浏览器在粘贴所选 HTML 时所做的那样

bra*_*obo 3 html javascript

如果我在页面中选择并复制样式良好的 HTML 表格(或任何其他元素),然后将其粘贴到 Gmail 或 Outlook 撰写界面中的新电子邮件中,则样式将通过样式内联保留。

例子:在此输入图像描述

我想通过 Javascript 触发 Chrome 生成用于粘贴的这种样式内联 HTML,以生成用于生成格式化 XLS 或电子邮件的 HTML。

0st*_*ne0 5

笔记:

  • 版本 3* 由于误读问题
  • 复制到剪贴板在 StackOverflow 代码片段中不起作用,请尝试离线

原始答案,使用getComputedStyle()

我们可以使用它getComputedStyle()来获取元素的所有计算样式。

我们可以将其映射到内联 css 并将其添加到 DOM 使用setAttribute

由于getComputedStyle()实际上返回了所有样式,因此大多数样式都不需要。我建议使用白名单样式。(参见下面的第二个片段)

小演示,按按钮复制文本。
所有div样式都将是内联的,在这个巨大列表中的某个位置将是border等等。

function getOuterHTMLWithInlineStyle(el) {
    let s = getComputedStyle(el);
    let i = []
    for (let key in s) {
        if (!Number.isInteger(+key)) {
          let prop = key.replace(/\-([a-z])/g, v => v[1].toUpperCase());
          i.push(`${key}: ${s[key]}`);
        }
    }
    
    el.setAttribute('style', i.join("; "));
    
    return el.outerHTML;
}

function copy() {
    const e = document.querySelector('div')
    const html = getOuterHTMLWithInlineStyle(e)
       
    navigator.clipboard.writeText(html).then(() => {
      console.log('Succesfully copied HTML to clipboard');
    }, function(err) {
      console.error('Could not copy text.\nTried to copy the following:\n', html);
    });
}
Run Code Online (Sandbox Code Playgroud)
div {
    padding: 5px 25px;
    border: 1px solid red; 
}
Run Code Online (Sandbox Code Playgroud)
<div>Hello World!</div>
<br>
<button onClick='copy()'>Click me to copy</button>
Run Code Online (Sandbox Code Playgroud)


第二个答案,使用白名单

与上面相同的演示,但添加了白名单: 将复制以下 HTML:

<div style="border: 1px solid rgb(255, 0, 0); padding: 5px 25px">Hello World!</div>
Run Code Online (Sandbox Code Playgroud)

function getOuterHTMLWithInlineStyle(el, whitelist = [ 'border', 'padding' ]) {
    let s = getComputedStyle(el);
    let i = []
    for (let key in s) {
        if (whitelist.includes(key)) {
          let prop = key.replace(/\-([a-z])/g, v => v[1].toUpperCase());
          i.push(`${key}: ${s[key]}`);
        }
    }
    
    el.setAttribute('style', i.join("; "));
    
    return el.outerHTML;
}

function copy() {
    const e = document.querySelector('div')
    const html = getOuterHTMLWithInlineStyle(e)
       
    navigator.clipboard.writeText(html).then(() => {
      console.log('Succesfully copied HTML to clipboard');
    }, function(err) {
      console.error('Could not copy text.\nTried to copy the following:\n', html);
    });
}
Run Code Online (Sandbox Code Playgroud)
div {
    padding: 5px 25px;
    border: 1px solid red; 
}
Run Code Online (Sandbox Code Playgroud)
<div>Hello World!</div>
<br>
<button onClick='copy()'>Click me to copy</button>
Run Code Online (Sandbox Code Playgroud)


第三个答案,使用document.styleSheets

好吧,v3,基于这个 SO 答案,用户使用它仅从样式表中document.styleSheets获取css并过滤那些非默认的样式表。

使用 amap()和正则表达式,我们可以获得一个仅包含您需要的 CSS 值的字符串。

请注意,这可能无法 100% 正常工作,正则表达式没有考虑 CSS 值可能包含{'s。如果您有非常复杂的值,您应该改进正则表达式。

下面的(折叠的)代码片段将输出/复制以下 HTML:

<div style="padding: 5px 25px; border: 1px solid red;">Hello World!</div>
Run Code Online (Sandbox Code Playgroud)

var proto = Element.prototype;
var slice = Function.call.bind(Array.prototype.slice);
var matches = Function.call.bind(proto.matchesSelector || 
                proto.mozMatchesSelector || proto.webkitMatchesSelector ||
                proto.msMatchesSelector || proto.oMatchesSelector);

var elementMatchCSSRule = function(element, cssRule) {
  return matches(element, cssRule.selectorText);
};

var cssRules = slice(document.styleSheets).reduce(function(rules, styleSheet) {
  return rules.concat(slice(styleSheet.cssRules));
}, []);

var getAppliedCss = function(elm) {
    var elementRules = cssRules.filter(elementMatchCSSRule.bind(null, elm));
    var rules =[];
    if (elementRules.length) {
        for (i = 0; i < elementRules.length; i++) {
            rules.push(elementRules[i].cssText)
        }       
    }
  
    return rules.map(r => /\{(.+)\}/g.exec(r)[1].trim()).join("; ");
}

function getOuterHTMLWithInlineStyle(el) {
    el.setAttribute('style', getAppliedCss(el));    
    return el.outerHTML;
}

function copy() {
    const e = document.querySelector('div')
    const html = getOuterHTMLWithInlineStyle(e)
       
    navigator.clipboard.writeText(html).then(() => {
      console.log('Succesfully copied HTML to clipboard');
    }, function(err) {
      console.error('Could not copy text.\nTried to copy the following:\n', html);
    });
}
Run Code Online (Sandbox Code Playgroud)
div {
    padding: 5px 25px;
    border: 1px solid red; 
}
Run Code Online (Sandbox Code Playgroud)
<div>Hello World!</div>
<br>
<button onClick='copy()'>Click me to copy</button>
Run Code Online (Sandbox Code Playgroud)