Skip to content

Commit

Permalink
Merge 33baae4 into 0596d22
Browse files Browse the repository at this point in the history
  • Loading branch information
fb55 committed Nov 22, 2022
2 parents 0596d22 + 33baae4 commit e1a677c
Show file tree
Hide file tree
Showing 11 changed files with 1,823 additions and 1,487 deletions.
8 changes: 4 additions & 4 deletions .eslintrc.json
Expand Up @@ -3,7 +3,7 @@
"extends": [
"eslint:recommended",
"plugin:jsdoc/recommended",
"plugin:node/recommended",
"plugin:n/recommended",
"prettier"
],
"env": { "node": true },
Expand Down Expand Up @@ -60,9 +60,9 @@
"jsdoc/valid-types": 2,
"jsdoc/tag-lines": 0,

"node/no-unsupported-features/es-syntax": 0,
"node/file-extension-in-import": ["error", "always"],
"node/no-missing-import": 0
"n/no-unsupported-features/es-syntax": 0,
"n/file-extension-in-import": ["error", "always"],
"n/no-missing-import": 0
},
"settings": {
"jsdoc": {
Expand Down
2 changes: 1 addition & 1 deletion benchmark/benchmark.ts
@@ -1,4 +1,4 @@
import Suites from './suite'; // eslint-disable-line node/file-extension-in-import
import Suites from './suite'; // eslint-disable-line n/file-extension-in-import
import type { Cheerio } from '../src/cheerio.js';
import type { Element } from 'domhandler';

Expand Down
2,921 changes: 1,453 additions & 1,468 deletions package-lock.json

Large diffs are not rendered by default.

32 changes: 24 additions & 8 deletions package.json
Expand Up @@ -30,7 +30,10 @@
"exports": {
".": {
"require": "./lib/index.js",
"import": "./lib/esm/index.js"
"import": {
"node": "./lib/esm/node.js",
"default": "./lib/esm/index.js"
}
},
"./lib/slim": {
"require": "./lib/slim.js",
Expand All @@ -39,6 +42,10 @@
"./lib/utils": {
"require": "./lib/utils.js",
"import": "./lib/esm/utils.js"
},
"./lib/node": {
"require": "./lib/node.js",
"import": "./lib/esm/node.js"
}
},
"files": [
Expand All @@ -52,32 +59,36 @@
"dom-serializer": "^2.0.0",
"domhandler": "^5.0.3",
"domutils": "^3.0.1",
"encoding-sniffer": "^0.0.1",
"htmlparser2": "^8.0.1",
"parse5": "^7.1.2",
"parse5-htmlparser2-tree-adapter": "^7.0.0"
"parse5-htmlparser2-tree-adapter": "^7.0.0",
"parse5-parser-stream": "^7.1.2",
"whatwg-mimetype": "^3.0.0"
},
"devDependencies": {
"@imgix/js-core": "^3.7.0",
"@octokit/graphql": "^5.0.4",
"@types/benchmark": "^2.1.2",
"@types/jest": "^28.1.8",
"@types/jest": "^29.2.3",
"@types/node": "^18.11.9",
"@types/whatwg-mimetype": "^3.0.0",
"@typescript-eslint/eslint-plugin": "^5.44.0",
"@typescript-eslint/parser": "^5.44.0",
"benchmark": "^2.1.4",
"eslint": "^8.28.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-jest": "^27.1.5",
"eslint-plugin-jsdoc": "^39.6.2",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-n": "^15.5.1",
"husky": "^8.0.2",
"jest": "^28.1.3",
"jest": "^29.3.1",
"jquery": "^3.6.1",
"jsdom": "^20.0.3",
"lint-staged": "^13.0.3",
"prettier": "^2.7.1",
"prettier-plugin-jsdoc": "0.4.2",
"ts-jest": "^28.0.8",
"ts-jest": "^29.0.3",
"ts-node": "^10.9.1",
"typedoc": "^0.23.21",
"typescript": "^4.9.3",
Expand Down Expand Up @@ -112,14 +123,19 @@
"lint-staged": {
"*.js": [
"prettier --write",
"npm run test:lint -- --fix"
"npm run lint:es -- --fix"
],
"*.{json,md,ts,yml}": [
"prettier --write"
]
},
"jest": {
"preset": "ts-jest",
"preset": "ts-jest/presets/default-esm",
"globals": {
"ts-jest": {
"useESM": true
}
},
"testEnvironment": "node",
"testPathIgnorePatterns": [
"/__fixtures__/"
Expand Down
2 changes: 1 addition & 1 deletion scripts/fetch-sponsors.ts
Expand Up @@ -5,7 +5,7 @@
* https://github.com/eslint/website/blob/230e73457dcdc2353ad7934e876a5a222a17b1d7/_tools/fetch-sponsors.js.
*/

import * as fs from 'fs/promises';
import * as fs from 'node:fs/promises';
import { request } from 'undici';
import { graphql as githubGraphQL } from '@octokit/graphql';
import ImgixClient from '@imgix/js-core';
Expand Down
4 changes: 2 additions & 2 deletions src/api/attributes.ts
Expand Up @@ -380,7 +380,7 @@ export function prop<T extends AnyNode>(
case 'src': {
const prop = el.attribs?.[name];

/* eslint-disable node/no-unsupported-features/node-builtins */
/* eslint-disable n/no-unsupported-features/node-builtins */
if (
typeof URL !== 'undefined' &&
((name === 'href' && (el.tagName === 'a' || el.name === 'link')) ||
Expand All @@ -395,7 +395,7 @@ export function prop<T extends AnyNode>(
) {
return new URL(prop, this.options.baseURI).href;
}
/* eslint-enable node/no-unsupported-features/node-builtins */
/* eslint-enable n/no-unsupported-features/node-builtins */

return prop;
}
Expand Down
2 changes: 1 addition & 1 deletion src/load.spec.ts
Expand Up @@ -24,7 +24,7 @@ describe('.load', () => {

it('(buffer) : should accept a buffer', () => {
const html = '<html><head></head><body>foo</body></html>';
// eslint-disable-next-line node/no-unsupported-features/node-builtins
// eslint-disable-next-line n/no-unsupported-features/node-builtins
const $html = cheerio.load(Buffer.from(html));
expect($html.html()).toBe(html);
});
Expand Down
163 changes: 163 additions & 0 deletions src/node.spec.ts
@@ -0,0 +1,163 @@
/* eslint-disable jest/no-done-callback */
import * as cheerio from './node.js';
import { Writable } from 'node:stream';
import { createServer, type Server } from 'node:http';

function noop() {
// Ignore
}

const TEST_HTML = '<h1>Hello World</h1>';
const TEST_HTML_UTF16 = Buffer.from(TEST_HTML, 'utf16le');
const TEST_HTML_UTF16_BOM = Buffer.from([
// UTF16-LE BOM
0xff,
0xfe,
...Array.from(TEST_HTML_UTF16),
]);

describe('loadBuffer', () => {
it('should parse UTF-8 HTML', () => {
const $ = cheerio.loadBuffer(Buffer.from(TEST_HTML));

expect($.html()).toBe(
`<html><head></head><body>${TEST_HTML}</body></html>`
);
});

it('should parse UTF-16 HTML', () => {
const $ = cheerio.loadBuffer(TEST_HTML_UTF16_BOM);

expect($.html()).toBe(
`<html><head></head><body>${TEST_HTML}</body></html>`
);
});
});

describe('stringStream', () => {
it('should use parse5 by default', (cb) => {
const stream = cheerio.stringStream({}, (err, $) => {
expect(err).toBeUndefined();

expect($.html()).toBe(
`<html><head></head><body>${TEST_HTML}</body></html>`
);

cb();
});
expect(stream).toBeInstanceOf(Writable);

stream.end(TEST_HTML);
});

it('should error from parse5 on buffer', () => {
const stream = cheerio.stringStream({}, noop);
expect(stream).toBeInstanceOf(Writable);

expect(() => stream.write(Buffer.from(TEST_HTML))).toThrow(
'Parser can work only with string streams.'
);
});

it('should use htmlparser2 for XML', (cb) => {
const stream = cheerio.stringStream({ xmlMode: true }, (err, $) => {
expect(err).toBeNull();

expect($.html()).toBe(TEST_HTML);

cb();
});
expect(stream).toBeInstanceOf(Writable);

stream.end(TEST_HTML);
});
});

describe('decodeStream', () => {
it('should use parse5 by default', (cb) => {
const stream = cheerio.decodeStream({}, (err, $) => {
expect(err).toBeUndefined();

expect($.html()).toBe(
`<html><head></head><body>${TEST_HTML}</body></html>`
);

cb();
});
expect(stream).toBeInstanceOf(Writable);

stream.end(TEST_HTML_UTF16_BOM);
});

it('should use htmlparser2 for XML', (cb) => {
const stream = cheerio.decodeStream({ xmlMode: true }, (err, $) => {
expect(err).toBeNull();

expect($.html()).toBe(TEST_HTML);

cb();
});
expect(stream).toBeInstanceOf(Writable);

stream.end(TEST_HTML_UTF16_BOM);
});
});

describe('fromURL', () => {
let server: Server | undefined;

function createTestServer(
contentType: string,
body: string | Buffer
): Promise<number> {
return new Promise((resolve, reject) => {
server = createServer((_req, res) => {
res.writeHead(200, { 'Content-Type': contentType });
res.end(body);
});

server.listen(0, () => {
const address = server?.address();

if (typeof address === 'string' || address == null) {
reject(new Error('Failed to get port'));
} else {
resolve(address.port);
}
});
});
}

afterEach((cb) => {
server?.close(cb);
server = undefined;
});

it('should fetch UTF-8 HTML', async () => {
const port = await createTestServer('text/html', TEST_HTML);
const $ = await cheerio.fromURL(`http://localhost:${port}`);

expect($.html()).toBe(
`<html><head></head><body>${TEST_HTML}</body></html>`
);
});

it('should fetch UTF-16 HTML', async () => {
const port = await createTestServer(
'text/html; charset=utf-16le',
TEST_HTML_UTF16
);
const $ = await cheerio.fromURL(`http://localhost:${port}`);

expect($.html()).toBe(
`<html><head></head><body>${TEST_HTML}</body></html>`
);
});

it('should parse XML based on Content-Type', async () => {
const port = await createTestServer('text/xml', TEST_HTML);
const $ = await cheerio.fromURL(`http://localhost:${port}`);

expect($.html()).toBe(TEST_HTML);
});
});

0 comments on commit e1a677c

Please sign in to comment.