taoqf / node-html-parser

A very fast HTML parser, generating a simplified DOM, with basic element query support.
MIT License
1.11k stars 107 forks source link

TypeError: elem.getAttribute is not a function #100

Closed moltar closed 3 years ago

moltar commented 3 years ago

Version 3.0.0 (or 3.0.1) seems to intro an error:

TypeError: elem.getAttribute is not a function

const html = parse('...')

// happens here
html.querySelector('#foo')
moltar commented 3 years ago
      at Object.getAttributeValue (node_modules/node-html-parser/dist/matcher.js:11:17)
      at node_modules/css-select/lib/attributes.js:32:28
      at Object.findOne (node_modules/node-html-parser/dist/matcher.js:68:13)
      at node_modules/css-select/lib/index.js:117:27
      at Object.select [as selectOne] (node_modules/css-select/lib/index.js:64:16)
      at HTMLElement.Object.<anonymous>.HTMLElement.querySelector (node_modules/node-html-parser/dist/nodes/html.js:421:29)

...
taoqf commented 3 years ago

I need more details. here is an example of id selector, and the tests passed.

olitoni commented 3 years ago

I've got the same issue

  let root = parse(data);
  let test = root.querySelectorAll('.observed');
  console.log(test[0].querySelector('.search'))

  //Returns:
  TypeError: elem.getAttribute is not a function
olitoni commented 3 years ago

Just tried, 2.1.0 works absolutely fine and returns the HTMLElement from the code above

kika commented 3 years ago

For me this error happens when there's no match for the selector.

moltar commented 3 years ago

For me this error happens when there's no match for the selector.

Most likely the same for me. I'm checking for the existence of an element that I expect to be absent most of the time.

kika commented 3 years ago

I got around by using querySelectorAll and checking the length of the result. But I'd expect querySelector to return a falsey value, not a trap.

taoqf commented 3 years ago

I got around by using querySelectorAll and checking the length of the result. But I'd expect querySelector to return a falsey value, not a trap.

May I know what is the html you parsed? I should do some tests and try to fix that.

Just tried, 2.1.0 works absolutely fine and returns the HTMLElement from the code above

It will be easier for me to have the html.

I did some tests like that:

const root = parse('<div class="a b"></div>');
root.querySelectorAll('a').length.should.eql(0);
should.equal(root.querySelector('a'), null);
root.querySelectorAll('.a').length.should.eql(1);
root.querySelectorAll('.b').length.should.eql(1);
should.notEqual(root.querySelector('.a'), null);
const nodelist = root.querySelectorAll('.a,.b');
nodelist.length.should.eql(1);
const div = nodelist[0];
root.querySelector('.a,.b').should.eql(div);
taoqf commented 3 years ago

I tried to fix the issue. If you guys won't give me any clue, I will publish 3.0.2 several hours later.

taoqf commented 3 years ago

I think I fixed the issue. 3.0.3 published.

taoqf commented 3 years ago

Thank all of you.

kika commented 3 years ago

Yeeep, can confirm, now querySelector works as expected if there's nothing in the HTML that matches the selector.

moltar commented 3 years ago

Thanks @taoqf! 🙌🏼