Skip to content
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

feat: Add ES6 module export #680

Merged
merged 5 commits into from
Dec 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,13 @@
"url": "https://github.com/sponsors/fb55"
},
"repository": {
"type": "git",
"url": "https://github.com/fb55/css-what"
},
"main": "lib/index.js",
"types": "lib/index.d.ts",
"main": "lib/commonjs/index.js",
"module": "lib/es/index.js",
"types": "lib/es/index.d.ts",
"sideEffects": false,
"files": [
"lib/**/*"
],
Expand All @@ -24,7 +27,7 @@
"format:es": "npm run lint:es -- --fix",
"format:prettier": "npm run prettier -- --write",
"prettier": "prettier '**/*.{ts,md,json,yml}'",
"build": "tsc",
"build": "tsc && tsc -p tsconfig.es.json",
"prepare": "npm run build"
},
"devDependencies": {
Expand All @@ -45,7 +48,10 @@
},
"license": "BSD-2-Clause",
"jest": {
"preset": "ts-jest"
"preset": "ts-jest",
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a way to test the ESM version of the module as well? Eg. if a __dirname was missed somewhere — would that be caught?

"roots": [
"src"
]
},
"prettier": {
"tabWidth": 4
Expand Down
6 changes: 3 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export * from "./parse";
export { default as parse } from "./parse";
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Won't imports have to be updated to include a .js extension?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically yes in order to get these to work in a browser it needs to have an extension. However both eslink-pluign-node and jest breaks if I change this to have .js extensions.

There is a long thread here:
microsoft/TypeScript#16577

Microsoft don't want to convert these paths to js paths on the fly but they seem to support them now however the rest of the tools for linting and testing here doesn't seem to suppot that. There are workaround for this that for example transpile the js files before being pushed to npm. I've seen people having scripts that just regexp replace this in source. It all depends on how much one want it to work with js modules in the browser. Bundlers will look for default file extensions so this is only an issue if you are loading scripts with <script type="module" src="main.js"></script>.

export { default as stringify } from "./stringify";
export * from "./types";
export { isTraversal, parse } from "./parse";
export { stringify } from "./stringify";
94 changes: 10 additions & 84 deletions src/parse.ts
Original file line number Diff line number Diff line change
@@ -1,83 +1,12 @@
export interface Options {
/**
* When false, tag names will not be lowercased.
* @default true
*/
lowerCaseAttributeNames?: boolean;
/**
* When false, attribute names will not be lowercased.
* @default true
*/
lowerCaseTags?: boolean;
/**
* When `true`, `xmlMode` implies both `lowerCaseTags` and `lowerCaseAttributeNames` are set to `false`.
* Also, `ignoreCase` on attributes will not be inferred based on HTML rules anymore.
* @default false
*/
xmlMode?: boolean;
}

export type Selector =
| PseudoSelector
| PseudoElement
| AttributeSelector
| TagSelector
| UniversalSelector
| Traversal;

export interface AttributeSelector {
type: "attribute";
name: string;
action: AttributeAction;
value: string;
ignoreCase: boolean | null;
namespace: string | null;
}

type DataType = Selector[][] | null | string;

export interface PseudoSelector {
type: "pseudo";
name: string;
data: DataType;
}

export interface PseudoElement {
type: "pseudo-element";
name: string;
}

export interface TagSelector {
type: "tag";
name: string;
namespace: string | null;
}

export interface UniversalSelector {
type: "universal";
namespace: string | null;
}

export interface Traversal {
type: TraversalType;
}

export type AttributeAction =
| "any"
| "element"
| "end"
| "equals"
| "exists"
| "hyphen"
| "not"
| "start";

export type TraversalType =
| "adjacent"
| "child"
| "descendant"
| "parent"
| "sibling";
import type {
Options,
Selector,
AttributeSelector,
Traversal,
AttributeAction,
TraversalType,
DataType,
} from "./types";

const reName = /^[^\\#]?(?:\\(?:[\da-f]{1,6}\s?|.)|[\w\-\u00b0-\uFFFF])+/;
const reEscape = /\\([\da-f]{1,6}\s?|(\s)|.)/gi;
Expand Down Expand Up @@ -220,10 +149,7 @@ function isWhitespace(c: string) {
* The first dimension represents selectors separated by commas (eg. `sub1, sub2`),
* the second contains the relevant tokens for that selector.
*/
export default function parse(
selector: string,
options?: Options
): Selector[][] {
export function parse(selector: string, options?: Options): Selector[][] {
const subselects: Selector[][] = [];

const endIndex = parseSelector(subselects, `${selector}`, options, 0);
Expand Down
4 changes: 2 additions & 2 deletions src/stringify.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Selector } from "./parse";
import type { Selector } from "./types";

const actionTypes: Record<string, string> = {
equals: "",
Expand Down Expand Up @@ -29,7 +29,7 @@ const charsToEscape = new Set([
*
* @param selector Selector to stringify.
*/
export default function stringify(selector: Selector[][]): string {
export function stringify(selector: Selector[][]): string {
return selector.map(stringifySubselector).join(", ");
}

Expand Down
80 changes: 80 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
export interface Options {
/**
* When false, tag names will not be lowercased.
* @default true
*/
lowerCaseAttributeNames?: boolean;
/**
* When false, attribute names will not be lowercased.
* @default true
*/
lowerCaseTags?: boolean;
/**
* When `true`, `xmlMode` implies both `lowerCaseTags` and `lowerCaseAttributeNames` are set to `false`.
* Also, `ignoreCase` on attributes will not be inferred based on HTML rules anymore.
* @default false
*/
xmlMode?: boolean;
}

export type Selector =
| PseudoSelector
| PseudoElement
| AttributeSelector
| TagSelector
| UniversalSelector
| Traversal;

export interface AttributeSelector {
type: "attribute";
name: string;
action: AttributeAction;
value: string;
ignoreCase: boolean | null;
namespace: string | null;
}

export type DataType = Selector[][] | null | string;

export interface PseudoSelector {
type: "pseudo";
name: string;
data: DataType;
}

export interface PseudoElement {
type: "pseudo-element";
name: string;
}

export interface TagSelector {
type: "tag";
name: string;
namespace: string | null;
}

export interface UniversalSelector {
type: "universal";
namespace: string | null;
}

export interface Traversal {
type: TraversalType;
}

export type AttributeAction =
| "any"
| "element"
| "end"
| "equals"
| "exists"
| "hyphen"
| "not"
| "start";

export type TraversalType =
| "adjacent"
| "child"
| "descendant"
| "parent"
| "sibling";
9 changes: 9 additions & 0 deletions tsconfig.es.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"target": "ES2019",
"module": "es2015",
"outDir": "lib/es",
"moduleResolution": "node"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does moduleResolution have to be set here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you don't specify node it will classic if you change module to es2015.
Described here: https://www.typescriptlang.org/docs/handbook/module-resolution.html#module-resolution-strategies

}
}
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"declaration": true /* Generates corresponding '.d.ts' file. */,
"declarationMap": true /* Generates a sourcemap for each corresponding '.d.ts' file. */,
// "sourceMap": true, /* Generates corresponding '.map' file. */
"outDir": "lib" /* Redirect output structure to the directory. */,
"outDir": "lib/commonjs" /* Redirect output structure to the directory. */,
// "importHelpers": true, /* Import emit helpers from 'tslib'. */

/* Strict Type-Checking Options */
Expand Down