Jsdom: 内部文本实现

创建于 2015-09-25  ·  26评论  ·  资料来源: jsdom/jsdom

jsdom是一个很棒的网页抓取工具。 然而, textContent是一种非常不方便的方式来获取 html2text 转换的可读文本。

有一篇精彩的文章介绍innerText在许多情况下可以忽略的

http://perfectkills.com/the-poor-misunderstood-innerText/

作者建议将getSelection().toString()作为一种非常缓慢的解决方法,但是getSelection尚未在jsdom 中实现。

你能考虑在jsdom 中实现innerText吗? 作者对此进行了很大的探索,他甚至在最后添加了一个简单的规范。

feature layout

最有用的评论

如果其他人遇到这个问题,我会更进一步,并使用sanitize-html包来基本上了解浏览器在做什么(注意我没有导入 JSDOM 设置,因为我发现它不需要将其放入我的 Jest 设置文件时,但如果您不使用 Jest,那么您将需要使用@bennypowers推荐的global.Element = (new JSDOM()).window.Element设置):

Object.defineProperty(global.Element.prototype, 'innerText', {
  get() {
    return sanitizeHtml(this.textContent, {
      allowedTags: [], // remove all tags and return text content only
      allowedAttributes: {}, // remove all tags and return text content only
    });
  },
  configurable: true, // make it so that it doesn't blow chunks on re-running tests with things like --watch
});

所有26条评论

什么可惜,四肢瘦长SelectioninnerText库与jsdom不兼容: https://github.com/timdown/rangy/issues/348

因此,innerText 不是标准的,并且没有在至少一个主要引擎(Firefox)中实现。 没有标准,我认为我们不应该实施它。

貌似有与规范草案这整个事情有些运动在这里。 另请参阅所有参考资料。 不过,回购没有问题,所以我想知道它已经完成了多少/进展会有多快。

Firefox 已实现: https :

WHATWG 需要批准: https :

从规范看来,如果没有基本的布局支持,我们似乎无法正确实现innerText

是的,无论如何,如果没有大量的基础设施工作,这在 jsdom 中实际上是无法实现的……没有人抱有希望 :(。

至于布局支持要求: https :

由于采用了 WHATWG,是否有计划实施它?

是的......虽然规范需要很多jsdom没有的东西,但围绕CSS框:(。不知道该怎么做。

是否有任何库可以与 jsdom 一起插入?

@domenic关心放弃一些关于为什么这是这样的基础设施大修的知识? 我们认为房间里 800 磅的大猩猩会离开 lo-key。 但看起来它不会去任何地方。 如你所知,我一直在思考 jsdom 的内部结构。 在 repo 中哪里是开始审查 jsdom newb 代码的好地方?

在此先感谢🙏 /cc @vsemozhetbyt

主要问题是innerText依靠布局引擎来指导这一事实,而 jsdom 没有布局引擎。 请参阅https://html.spec.whatwg.org/multipage/dom.html#the -innertext-idl-attribute 和
http://perfectkills.com/the-poor-misunderstood-innerText/ 。 从第二个链接:

请注意 innerText 如何几乎精确地表示文本在页面上的显示方式。 另一方面,textContent 做了一些奇怪的事情——它忽略了由
以及围绕样式块元素(在这种情况下)。

仍然超出范围并且没有解决方法?

显然,规范说:

如果这个元素没有被渲染,或者如果用户代理是一个非 CSS 用户代理, [emphasis added] 那么返回与这个元素的 textContent IDL 属性相同的值。

我认为一种解决方法是简单地返回textContent

我们实现了足够多的 CSS,我认为这并不适用。 我们只是不实现布局部分......

大家好,这个有消息吗?

只需使用无头镀铬:)

@domenic来自@coreh提到的规范:
https://html.spec.whatwg.org/multipage/dom.html#the -innertext-idl-attribute

如果这个元素没有被渲染,或者如果用户代理是一个非 CSS 用户代理,那么返回与这个元素上的textContent IDL 属性相同的值。

https://html.spec.whatwg.org/multipage/rendering.html#being -rendered

如果元素具有任何关联的 CSS 布局框、SVG 布局框或其他样式语言中的等效项,则该元素正在被渲染

如果jsdom没有实现布局部分,那是不是意味着“不被渲染”适用?

此消息适用于到达此 github 线程的任何人,他们只想通过一种方法在不更改其函数实现的情况下让他们的测试通过。

copypasta 用于测试文件的顶部:

// Expose JSDOM Element constructor
global.Element = (new JSDOM()).window.Element;
// 'Implement' innerText in JSDOM: https://github.com/jsdom/jsdom/issues/1245
Object.defineProperty(global.Element.prototype, 'innerText', {
  get() {
    return this.textContent;
  },
});

当然,上述讨论中的警告也适用。

如果其他人遇到这个问题,我会更进一步,并使用sanitize-html包来基本上了解浏览器在做什么(注意我没有导入 JSDOM 设置,因为我发现它不需要将其放入我的 Jest 设置文件时,但如果您不使用 Jest,那么您将需要使用@bennypowers推荐的global.Element = (new JSDOM()).window.Element设置):

Object.defineProperty(global.Element.prototype, 'innerText', {
  get() {
    return sanitizeHtml(this.textContent, {
      allowedTags: [], // remove all tags and return text content only
      allowedAttributes: {}, // remove all tags and return text content only
    });
  },
  configurable: true, // make it so that it doesn't blow chunks on re-running tests with things like --watch
});

我有类似的需求,但想比仅仅使用textContent更进一步——同样,这不能准确表示浏览器的实际操作,尤其是对于 css 隐藏的元素,但这很好足以满足我的用例:

function innerText(el)
  el = el.cloneNode(true) // can skip if mutability isn't a concern
  el.querySelectorAll('script,style').forEach(s => s.remove())
  return el.textContent
}

真可惜!

显然,规范说:

如果这个元素没有被渲染,或者如果用户代理是一个非 CSS 用户代理,[emphasis added] 那么返回与这个元素的 textContent IDL 属性相同的值。

我认为一种解决方法是简单地返回 textContent。

我们实现了足够多的 CSS,我认为这并不适用。 我们只是不实现布局部分......

@domenic请考虑对规范进行更自由的解释

当 CSS 规则的应用成本太高时,明确允许textContent作为后备

此外,innerText 被指定为getter 和 setter

鉴于我是规范编辑,我可以肯定地说“当 CSS 规则的应用成本太高时”并不是规范所说的。

..这是我对“如果用户代理是非 CSS 用户代理”的解释

“CSS 用户代理”和“非 CSS 用户代理”有什么区别?

关于什么:
CSS 用户代理可以“应用 CSS 规则”并输出结果(图形或文本)
非 CSS 用户代理太笨了,无法“应用 CSS 规则”

我们实现了足够多的 CSS,我认为这并不适用。

你是什​​么意思? window.getComputedStyle?

回退到 textContent 仍然比不实现标准接口好

也许我们可以只使用textContent值替换的结果innerText同时运行与测试jsdom 。 例如:

describe('mytest', () => {
  beforeAll(() => {
    Object.defineProperty(HTMLElement.prototype, 'innerText', {
      get() {
        return this.textContent;
      }
    });
  });
  it('should ok', () => {
  // test assertions
  });
});
此页面是否有帮助?
0 / 5 - 0 等级

相关问题

vsemozhetbyt picture vsemozhetbyt  ·  4评论

domenic picture domenic  ·  3评论

khalyomede picture khalyomede  ·  3评论

kilianc picture kilianc  ·  4评论

philipwalton picture philipwalton  ·  4评论