-
Notifications
You must be signed in to change notification settings - Fork 706
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
New: Add a standalone parser-html
#1277
Conversation
@@ -242,6 +245,17 @@ export default class LocalConnector implements IConnector { | |||
}); | |||
} | |||
|
|||
private watchForWindow() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will work if there is more than one html file?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will only populate the connector for the target HTML file as the connector APIs are tied to that singleton as far as I could tell.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To further clarify, if connector-local
is used with a glob pattern matching multiple HTML files, only the first one parsed will be used to populate DOM-related connector APIs.
Note in the context of the VS Code extension, connector-local
will be called separately for each file so this is not an issue there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, the problem will be with a glob pattern.
I think you need to touch a little bit how the connector works to support multiple HTMLs.
Right now, the fetch is in parallel, but maybe you can refactor the code to emit the fetch::end::html
serially so you can set the properties in the connector for each html, this way, the connector will support the parse-html
for all the HTML files. Do you know what I mean?
The idea is when the connector store all the HTMLs in an array, without emits the fetch::end::html
. Then, iterate that array serially doing:
- emit the
fetch::end::html
- in the event
parse::html
setthis._window
- wait until the analysis of the html finish.
- clean
this._window
- go to the next html.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense and doesn't look too difficult from glancing at the code. I'll see if I can incorporate this tomorrow.
@@ -1,4 +1,5 @@ | |||
import { IAsyncHTMLDocument, IAsyncHTMLElement } from './async-html'; //eslint-disable-line | |||
import { IAsyncHTMLDocument, IAsyncHTMLElement, IAsyncWindow } from './async-html'; //eslint-disable-line |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does it happen if you remove //eslint-disable-line
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nothing it seems. Want me to remove it? I was originally only making necessary changes (as this comment was already in the file), but it's an easy change so I can include the removal in this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes please. I saw it wasn't your change, but it would be nice to remove it :)
packages/parser-html/package.json
Outdated
"watch:test": "ava --watch", | ||
"watch:ts": "npm run build:ts -- --watch" | ||
}, | ||
"version": "0.0.1" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1.0.0
@@ -7,6 +7,7 @@ | |||
"timeout": "1m" | |||
}, | |||
"dependencies": { | |||
"@hint/parser-html": "^0.0.1", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note to self: Move this into a different commit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Honestly that should be a dev dependency as it's only used for types (specifically the HTMLParse
event). The only functional tie connector-local
has to the parser-html
is via the parse::html::end
event. I'll fix it (though that probably doesn't change your need to add even the dev dependency in a separate commit).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was referring a different commit, not anything about code changes.
That is for the release process.
this._window = null; | ||
|
||
const setWindow = (event: HTMLParse) => { | ||
this._window = event.window; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This also needs to emit a can-evaluate::script
event here or hint-axe
and friends won't work. I'll update the PR for this in a bit (need to grab a bite to eat).
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
FYI, I merged and tested this with the VSCode extension PR and it worked (although error positions will need a bit of work as expected). Even got |
🎉🎉🎉 |
Everything is failing because
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
packages/parser-html/README.md
Outdated
|
||
Note: This parser is not needed if using a [connector][connectors] | ||
which connects to a browser as the browser's DOM will be used to | ||
generate events instead. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The jsdom
connector doesn't need it neither. Maybe reformulate to say it's only required by local
?
packages/parser-html/src/parser.ts
Outdated
const resource = this._url = fetchEnd.response.url; | ||
|
||
const html = fetchEnd.response.body.content; | ||
const dom = new JSDOM(html, { runScripts: 'outside-only' }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe add a comment here explaining why we want outside-only
for future us?
packages/parser-html/src/parser.ts
Outdated
|
||
await this.engine.emitAsync(`traverse::up`, traverseEvent); | ||
|
||
return Promise.resolve(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are already using await
through this method so you shouldn't need to return a Promise
. Is TS complaining?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
packages/parser-html/README.md
Outdated
@@ -0,0 +1,60 @@ | |||
# HTML parser (`@hint/parser-html`) | |||
|
|||
The `HTML` parser is built on top of `[jsdom][jsdom]` so hints can |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[`jsdom`][jsdom]
packages/parser-html/package.json
Outdated
}, | ||
"description": "webhint parser needed to analyze HTML files", | ||
"devDependencies": { | ||
"@types/cheerio": "^0.22.9", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is no longer needed?
packages/parser-html/package.json
Outdated
"@types/cheerio": "^0.22.9", | ||
"@types/debug": "0.0.30", | ||
"@types/jsdom": "^11.0.6", | ||
"@types/node": "8.0.14", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove types that are not necessary.
(we try to keep them to a minimum, because they often break our builds 😔)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, after you do these changes, can you run yarn
in the root so that yarn.lock
file gets updated. Thanks!
packages/parser-html/tests/parser.ts
Outdated
}); | ||
}); | ||
|
||
test.serial('If fetch::end::html is received, then we should parse the code and emit a parse::html::end event', async (t) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If 'fetch::end::html' is received, then the code should be parsed and the `parse::html::end` event emitted
@alrra do you want me to rebase and resolve the |
Yes, thanks! Just remove the |
For use by `connector-local`. Currently uses `cheerio`, but may need to be cut-over to `jsdom` (with scripts and resource loading disabled) to maximize support for existing hints (e.g. `hint-axe`).
Currently requires parser-html to be explicitly add to the config for the data to be populated.
Includes changes to `connector-local` to implement `evaluate` and `querySelectorAll` based upon the new backing.
I missed adding a property on the new `IAsyncWindow` interface which was causing the tests to fail. I thought I had re-run the tests after that change, but apparently not.
I started using `engine.on` to listen for `parse::html::end`. Since this wasn't in the mock for `t.context.engine` one of the early tests failed (and the rest generated the error `'Attempted to wrap default which is already wrapped'` since the test didn't clean up.
Accomplished by keeping the fetch in parallel, but emitting the `fetch::end::${type}` events serially so we can have the correct internal `_window` reference during `hint` execution for each file (per David's suggestion). Also emit the `can-evaluate::script` event so `hint-axe` and others which need to inject script will do so.
Also fix JSDOM options to include source locations for elements.
Turns out `test-only` wasn't defined. I'll be fixing this in the template for `create-parser` in a separate commit.
Conditional on `#if official` (per Anton's recommendation) since it's only needed in the CI for `hint` itself.
Includes updating `yarn.lock`.
Pull request checklist
Make sure you:
For non-trivial changes, please make sure you also:
Short description of the change(s)
For use by
connector-local
in support of #1254 so we can expand theset of hints which run in the VSCode extension.
Uses
jsdom
(with scripts and resource loading disabled) to maximizesupport for existing hints (e.g.
hint-axe
).