diff --git a/.eslintrc.json b/.eslintrc.json index 2522061174..c6e793864c 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -61,7 +61,8 @@ "jsdoc/tag-lines": 0, "node/no-unsupported-features/es-syntax": 0, - "node/no-missing-import": [2, { "tryExtensions": [".js", ".json", ".ts"] }] + "node/file-extension-in-import": ["error", "always"], + "node/no-missing-import": 0 }, "settings": { "jsdoc": { diff --git a/benchmark/benchmark.ts b/benchmark/benchmark.ts index 45dcbc77df..178625eaba 100755 --- a/benchmark/benchmark.ts +++ b/benchmark/benchmark.ts @@ -1,5 +1,5 @@ -import Suites from './suite'; -import type { Cheerio } from '../src/cheerio'; +import Suites from './suite'; // eslint-disable-line node/file-extension-in-import +import type { Cheerio } from '../src/cheerio.js'; import type { Element } from 'domhandler'; const suites = new Suites(); diff --git a/benchmark/suite.ts b/benchmark/suite.ts index a93fb624c1..8a8db68caf 100644 --- a/benchmark/suite.ts +++ b/benchmark/suite.ts @@ -5,7 +5,7 @@ import { Suite, Event } from 'benchmark'; // @ts-expect-error `jsdom` types currently collide with `parse5` types. import { JSDOM } from 'jsdom'; import { Script } from 'vm'; -import cheerio from '../src'; +import cheerio from '../lib/index.js'; const documentDir = path.join(__dirname, 'documents'); const jQuerySrc = fs.readFileSync( diff --git a/package.json b/package.json index bd0dee1e1c..3fd433463a 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,17 @@ "homepage": "https://cheerio.js.org/", "main": "lib/index.js", "types": "lib/index.d.ts", + "module": "lib/esm/index.js", + "exports": { + ".": { + "require": "./lib/index.js", + "import": "./lib/esm/index.js" + }, + "./lib/slim": { + "require": "./lib/slim.js", + "import": "./lib/esm/slim.js" + } + }, "files": [ "lib" ], @@ -80,10 +91,12 @@ "format:prettier": "npm run format:prettier:raw -- --write", "format:prettier:raw": "prettier \"**/*.{{m,c,}js,ts,md,json,yml}\" --ignore-path .gitignore", "build:docs": "typedoc --hideGenerator src/index.ts", - "benchmark": "ts-node benchmark/benchmark.ts --regex \"^(?!.*highmem)\"", + "benchmark": "npm run build:cjs && ts-node benchmark/benchmark.ts --regex \"^(?!.*highmem)\"", "update-sponsors": "ts-node scripts/fetch-sponsors.ts", "bench": "npm run benchmark", - "build": "tsc", + "build": "npm run build:cjs && npm run build:esm", + "build:cjs": "tsc --sourceRoot https://raw.githubusercontent.com/cheeriojs/cheerio/$(git rev-parse HEAD)/src/", + "build:esm": "npm run build:cjs -- --module esnext --target es2019 --outDir lib/esm && echo '{\"type\":\"module\"}' > lib/esm/package.json", "prepublishOnly": "npm run build", "prepare": "husky install" }, @@ -107,6 +120,9 @@ "testPathIgnorePatterns": [ "/__fixtures__/" ], - "coverageProvider": "v8" + "coverageProvider": "v8", + "moduleNameMapper": { + "^(.*)\\.js$": "$1" + } } } diff --git a/src/__tests__/deprecated.spec.ts b/src/__tests__/deprecated.spec.ts index bdf47944de..42d5bff9b4 100644 --- a/src/__tests__/deprecated.spec.ts +++ b/src/__tests__/deprecated.spec.ts @@ -3,7 +3,7 @@ * removed in the next major release of Cheerio, but their stability should be * maintained until that time. */ -import * as fixtures from '../__fixtures__/fixtures'; +import * as fixtures from '../__fixtures__/fixtures.js'; import cheerio from '..'; describe('deprecated APIs', () => { diff --git a/src/__tests__/xml.spec.ts b/src/__tests__/xml.spec.ts index 7cd3374001..84a1135ddd 100644 --- a/src/__tests__/xml.spec.ts +++ b/src/__tests__/xml.spec.ts @@ -1,5 +1,5 @@ import cheerio from '..'; -import type { CheerioOptions } from '../options'; +import type { CheerioOptions } from '../options.js'; function xml(str: string, options?: CheerioOptions) { options = { xml: true, ...options }; diff --git a/src/api/attributes.spec.ts b/src/api/attributes.spec.ts index ec60bb3ddc..fccdf90265 100644 --- a/src/api/attributes.spec.ts +++ b/src/api/attributes.spec.ts @@ -1,5 +1,5 @@ import cheerio from '..'; -import type { Cheerio } from '../cheerio'; +import type { Cheerio } from '../cheerio.js'; import type { Element } from 'domhandler'; import { script, @@ -9,7 +9,7 @@ import { chocolates, inputs, mixedText, -} from '../__fixtures__/fixtures'; +} from '../__fixtures__/fixtures.js'; describe('$(...)', () => { let $: typeof cheerio; diff --git a/src/api/attributes.ts b/src/api/attributes.ts index a4b70c21d0..f78327b238 100644 --- a/src/api/attributes.ts +++ b/src/api/attributes.ts @@ -4,10 +4,10 @@ * @module cheerio/attributes */ -import { text } from '../static'; -import { isTag, domEach, camelCase, cssCase } from '../utils'; +import { text } from '../static.js'; +import { isTag, domEach, camelCase, cssCase } from '../utils.js'; import type { AnyNode, Element } from 'domhandler'; -import type { Cheerio } from '../cheerio'; +import type { Cheerio } from '../cheerio.js'; import { innerText, textContent } from 'domutils'; const hasOwn = Object.prototype.hasOwnProperty; const rspace = /\s+/; diff --git a/src/api/css.spec.ts b/src/api/css.spec.ts index 25adad0fb2..0eccb70c81 100644 --- a/src/api/css.spec.ts +++ b/src/api/css.spec.ts @@ -1,7 +1,7 @@ import cheerio from '..'; -import type { Cheerio } from '../cheerio'; +import type { Cheerio } from '../cheerio.js'; import type { Element } from 'domhandler'; -import { mixedText } from '../__fixtures__/fixtures'; +import { mixedText } from '../__fixtures__/fixtures.js'; describe('$(...)', () => { describe('.css', () => { diff --git a/src/api/css.ts b/src/api/css.ts index 2a63767823..10dd344f72 100644 --- a/src/api/css.ts +++ b/src/api/css.ts @@ -1,6 +1,6 @@ -import { domEach, isTag } from '../utils'; +import { domEach, isTag } from '../utils.js'; import type { Element, AnyNode } from 'domhandler'; -import type { Cheerio } from '../cheerio'; +import type { Cheerio } from '../cheerio.js'; /** * Get the value of a style property for the first element in the set of matched elements. diff --git a/src/api/forms.spec.ts b/src/api/forms.spec.ts index c6ca427829..082ff2582d 100644 --- a/src/api/forms.spec.ts +++ b/src/api/forms.spec.ts @@ -1,6 +1,6 @@ import cheerio from '../../src'; -import type { CheerioAPI } from '../load'; -import { forms } from '../__fixtures__/fixtures'; +import type { CheerioAPI } from '../load.js'; +import { forms } from '../__fixtures__/fixtures.js'; describe('$(...)', () => { let $: CheerioAPI; diff --git a/src/api/forms.ts b/src/api/forms.ts index cc0df8a9e5..6116cdd77e 100644 --- a/src/api/forms.ts +++ b/src/api/forms.ts @@ -1,6 +1,6 @@ import type { AnyNode } from 'domhandler'; -import type { Cheerio } from '../cheerio'; -import { isTag } from '../utils'; +import type { Cheerio } from '../cheerio.js'; +import { isTag } from '../utils.js'; /* * https://github.com/jquery/jquery/blob/2.1.3/src/manipulation/var/rcheckableType.js diff --git a/src/api/manipulation.spec.ts b/src/api/manipulation.spec.ts index d382ef09f7..34bbf911f0 100644 --- a/src/api/manipulation.spec.ts +++ b/src/api/manipulation.spec.ts @@ -1,6 +1,6 @@ import { load } from '../../src'; import type { CheerioAPI, Cheerio } from '..'; -import { fruits, divcontainers, mixedText } from '../__fixtures__/fixtures'; +import { fruits, divcontainers, mixedText } from '../__fixtures__/fixtures.js'; import type { AnyNode, Element } from 'domhandler'; describe('$(...)', () => { diff --git a/src/api/manipulation.ts b/src/api/manipulation.ts index 8799fe07b7..d79735f3a8 100644 --- a/src/api/manipulation.ts +++ b/src/api/manipulation.ts @@ -5,12 +5,12 @@ */ import { ParentNode, AnyNode, Element, Text, hasChildren } from 'domhandler'; -import { update as updateDOM } from '../parse'; -import { text as staticText } from '../static'; -import { domEach, cloneDom, isTag, isHtml, isCheerio } from '../utils'; +import { update as updateDOM } from '../parse.js'; +import { text as staticText } from '../static.js'; +import { domEach, cloneDom, isTag, isHtml, isCheerio } from '../utils.js'; import { removeElement } from 'domutils'; -import type { Cheerio } from '../cheerio'; -import type { BasicAcceptedElems, AcceptedElems } from '../types'; +import type { Cheerio } from '../cheerio.js'; +import type { BasicAcceptedElems, AcceptedElems } from '../types.js'; /** * Create an array of nodes, recursing into arrays and parsing strings if necessary. diff --git a/src/api/traversing.spec.ts b/src/api/traversing.spec.ts index 7c6ebe370a..94893bfedb 100644 --- a/src/api/traversing.spec.ts +++ b/src/api/traversing.spec.ts @@ -1,6 +1,6 @@ import cheerio from '../../src'; -import { Cheerio } from '../cheerio'; -import type { CheerioAPI } from '../load'; +import { Cheerio } from '../cheerio.js'; +import type { CheerioAPI } from '../load.js'; import { AnyNode, Element, Text, isText } from 'domhandler'; import { food, @@ -11,7 +11,7 @@ import { forms, mixedText, vegetables, -} from '../__fixtures__/fixtures'; +} from '../__fixtures__/fixtures.js'; function getText(el: Cheerio) { if (!el.length) return undefined; diff --git a/src/api/traversing.ts b/src/api/traversing.ts index 40470172e3..08f3a542aa 100644 --- a/src/api/traversing.ts +++ b/src/api/traversing.ts @@ -11,10 +11,10 @@ import { isDocument, Document, } from 'domhandler'; -import type { Cheerio } from '../cheerio'; +import type { Cheerio } from '../cheerio.js'; import * as select from 'cheerio-select'; -import { domEach, isTag, isCheerio } from '../utils'; -import { contains } from '../static'; +import { domEach, isTag, isCheerio } from '../utils.js'; +import { contains } from '../static.js'; import { getChildren, getSiblings, @@ -22,7 +22,7 @@ import { prevElementSibling, uniqueSort, } from 'domutils'; -import type { FilterFunction, AcceptedFilters } from '../types'; +import type { FilterFunction, AcceptedFilters } from '../types.js'; const reSiblingSelector = /^\s*[~+]/; /** diff --git a/src/cheerio.spec.ts b/src/cheerio.spec.ts index c93d44bd28..29e005ea84 100644 --- a/src/cheerio.spec.ts +++ b/src/cheerio.spec.ts @@ -1,10 +1,10 @@ import { parseDOM } from 'htmlparser2'; import cheerio from '.'; -import * as utils from './utils'; -import { fruits, food, noscript } from './__fixtures__/fixtures'; -import type { Cheerio } from './cheerio'; +import * as utils from './utils.js'; +import { fruits, food, noscript } from './__fixtures__/fixtures.js'; +import type { Cheerio } from './cheerio.js'; import type { Element } from 'domhandler'; -import type { CheerioOptions } from './options'; +import type { CheerioOptions } from './options.js'; declare module '.' { interface Cheerio { diff --git a/src/cheerio.ts b/src/cheerio.ts index f7fbacdf20..e3824e0cf6 100644 --- a/src/cheerio.ts +++ b/src/cheerio.ts @@ -1,12 +1,12 @@ -import type { InternalOptions } from './options'; +import type { InternalOptions } from './options.js'; import type { AnyNode, Document, ParentNode } from 'domhandler'; -import type { BasicAcceptedElems } from './types'; +import type { BasicAcceptedElems } from './types.js'; -import * as Attributes from './api/attributes'; -import * as Traversing from './api/traversing'; -import * as Manipulation from './api/manipulation'; -import * as Css from './api/css'; -import * as Forms from './api/forms'; +import * as Attributes from './api/attributes.js'; +import * as Traversing from './api/traversing.js'; +import * as Manipulation from './api/manipulation.js'; +import * as Css from './api/css.js'; +import * as Forms from './api/forms.js'; type AttributesType = typeof Attributes; type TraversingType = typeof Traversing; diff --git a/src/index.spec.ts b/src/index.spec.ts index ef755e40d3..0ad8c2fddc 100644 --- a/src/index.spec.ts +++ b/src/index.spec.ts @@ -1,5 +1,5 @@ -import * as cheerio from './index'; -import * as statics from './static'; +import * as cheerio from './index.js'; +import * as statics from './static.js'; describe('index', () => { it('should export all static methods', () => { diff --git a/src/index.ts b/src/index.ts index 09c4ec5c2d..94b8f2d49e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,19 +3,19 @@ * * @category Cheerio */ -export type { Cheerio } from './cheerio'; +export type { Cheerio } from './cheerio.js'; /** * Types used in signatures of Cheerio methods. * * @category Cheerio */ -export * from './types'; +export * from './types.js'; export type { CheerioOptions, HTMLParser2Options, Parse5Options, -} from './options'; +} from './options.js'; /** * Re-exporting all of the node types. * @@ -23,10 +23,10 @@ export type { */ export type { Node, NodeWithChildren, Element, Document } from 'domhandler'; -export type { CheerioAPI } from './load'; -import { getLoad } from './load'; -import { getParse } from './parse'; -import { renderWithParse5, parseWithParse5 } from './parsers/parse5-adapter'; +export type { CheerioAPI } from './load.js'; +import { getLoad } from './load.js'; +import { getParse } from './parse.js'; +import { renderWithParse5, parseWithParse5 } from './parsers/parse5-adapter.js'; import renderWithHtmlparser2 from 'dom-serializer'; import { parseDocument as parseWithHtmlparser2 } from 'htmlparser2'; @@ -83,9 +83,9 @@ import { filters, pseudos, aliases } from 'cheerio-select'; */ export const select = { filters, pseudos, aliases }; -export * from './static'; +export * from './static.js'; -import * as staticMethods from './static'; +import * as staticMethods from './static.js'; /** * In order to promote consistency with the jQuery library, users are encouraged diff --git a/src/load.ts b/src/load.ts index 2038f222a7..a1161f904d 100644 --- a/src/load.ts +++ b/src/load.ts @@ -3,12 +3,12 @@ import { InternalOptions, default as defaultOptions, flatten as flattenOptions, -} from './options'; -import * as staticMethods from './static'; -import { Cheerio } from './cheerio'; -import { isHtml, isCheerio } from './utils'; +} from './options.js'; +import * as staticMethods from './static.js'; +import { Cheerio } from './cheerio.js'; +import { isHtml, isCheerio } from './utils.js'; import type { AnyNode, Document, Element, ParentNode } from 'domhandler'; -import type { SelectorType, BasicAcceptedElems } from './types'; +import type { SelectorType, BasicAcceptedElems } from './types.js'; type StaticType = typeof staticMethods; diff --git a/src/parse.spec.ts b/src/parse.spec.ts index 2931758a2f..4b29d384fd 100644 --- a/src/parse.spec.ts +++ b/src/parse.spec.ts @@ -1,9 +1,9 @@ import type { Document, Element } from 'domhandler'; -import { getParse } from './parse'; -import defaultOpts from './options'; +import { getParse } from './parse.js'; +import defaultOpts from './options.js'; import { parseDocument as parseWithHtmlparser2 } from 'htmlparser2'; -import { parseWithParse5 } from './parsers/parse5-adapter'; +import { parseWithParse5 } from './parsers/parse5-adapter.js'; const parse = getParse((content, options, isDocument, context) => options.xmlMode || options._useHtmlParser2 diff --git a/src/parse.ts b/src/parse.ts index 6ade82560e..c4dda11067 100644 --- a/src/parse.ts +++ b/src/parse.ts @@ -5,7 +5,7 @@ import { ParentNode, isDocument as checkIsDocument, } from 'domhandler'; -import type { InternalOptions } from './options'; +import type { InternalOptions } from './options.js'; /* * Parser diff --git a/src/parsers/parse5-adapter.ts b/src/parsers/parse5-adapter.ts index d59f36d0d9..9d802fadee 100644 --- a/src/parsers/parse5-adapter.ts +++ b/src/parsers/parse5-adapter.ts @@ -1,7 +1,7 @@ import { AnyNode, Document, isDocument, ParentNode } from 'domhandler'; import { parse as parseDocument, parseFragment, serializeOuter } from 'parse5'; import { adapter as htmlparser2Adapter } from 'parse5-htmlparser2-tree-adapter'; -import type { InternalOptions } from '../options'; +import type { InternalOptions } from '../options.js'; export function parseWithParse5( content: string, diff --git a/src/slim.ts b/src/slim.ts index 1dfe839cfa..7bdd090308 100644 --- a/src/slim.ts +++ b/src/slim.ts @@ -16,10 +16,10 @@ export type { * * @category Cheerio */ -export * from './types'; +export * from './types.js'; -import { getLoad } from './load'; -import { getParse } from './parse'; +import { getLoad } from './load.js'; +import { getParse } from './parse.js'; import render from 'dom-serializer'; import { parseDocument } from 'htmlparser2'; diff --git a/src/static.spec.ts b/src/static.spec.ts index 9b7f7f7c16..9f5aff2a72 100644 --- a/src/static.spec.ts +++ b/src/static.spec.ts @@ -1,4 +1,4 @@ -import * as fixtures from './__fixtures__/fixtures'; +import * as fixtures from './__fixtures__/fixtures.js'; import cheerio, { CheerioAPI } from '.'; describe('cheerio', () => { diff --git a/src/static.ts b/src/static.ts index cba34410c6..463383bd82 100644 --- a/src/static.ts +++ b/src/static.ts @@ -1,4 +1,4 @@ -import type { BasicAcceptedElems } from './types'; +import type { BasicAcceptedElems } from './types.js'; import type { CheerioAPI, Cheerio } from '.'; import { AnyNode, Document, isText, hasChildren } from 'domhandler'; import { @@ -6,7 +6,7 @@ import { CheerioOptions, default as defaultOptions, flatten as flattenOptions, -} from './options'; +} from './options.js'; import { ElementType } from 'htmlparser2'; /** diff --git a/src/types.ts b/src/types.ts index 7cc41c6275..99b5b9efd8 100644 --- a/src/types.ts +++ b/src/types.ts @@ -40,7 +40,7 @@ export type SelectorType = | `${SelectorSpecial}${AlphaNumeric}${string}` | `${AlphaNumeric}${string}`; -import type { Cheerio } from './cheerio'; +import type { Cheerio } from './cheerio.js'; import type { AnyNode } from 'domhandler'; /** Elements that can be passed to manipulation methods. */ diff --git a/src/utils.ts b/src/utils.ts index 88f65930ee..3114a11370 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,5 +1,5 @@ import { type AnyNode, cloneNode, Document } from 'domhandler'; -import type { Cheerio } from './cheerio'; +import type { Cheerio } from './cheerio.js'; /** * Check if the DOM element is a tag.