Skip to content

Commit

Permalink
Use ESM
Browse files Browse the repository at this point in the history
  • Loading branch information
wooorm committed Apr 28, 2021
1 parent 6ad87e6 commit 5573ee1
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 77 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
.DS_Store
*.log
.nyc_output/
coverage/
node_modules/
yarn.lock
1 change: 0 additions & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
coverage/
*.json
*.md
29 changes: 13 additions & 16 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,27 @@
'use strict'

module.exports = fromSelector

var h = require('hastscript')
var s = require('hastscript/svg')
var zwitch = require('zwitch')
var Parser = require('css-selector-parser').CssSelectorParser
import {h, s} from 'hastscript'
import {zwitch} from 'zwitch'
import {CssSelectorParser} from 'css-selector-parser'

var compile = zwitch('type', {
handlers: {
selectors: selectors,
ruleSet: ruleSet,
rule: rule
selectors,
ruleSet,
rule
}
})

var parser = new Parser()
var parser = new CssSelectorParser()

parser.registerNestingOperators('>', '+', '~')
// Register these so we can throw nicer errors.
parser.registerAttrEqualityMods('~', '|', '^', '$', '*')

function fromSelector(selector, space) {
export function fromSelector(selector, space) {
var config = {space: (space && space.space) || space || 'html', root: true}

return compile(parser.parse(selector || ''), config) || build(config.space)()
return (
compile(parser.parse(selector || ''), config) || build(config.space)('')
)
}

function selectors() {
Expand All @@ -37,7 +34,7 @@ function ruleSet(query, config) {

function rule(query, config) {
var parentSpace = config.space
var name = query.tagName === '*' ? '' : query.tagName
var name = query.tagName === '*' ? '' : query.tagName || ''
var space = parentSpace === 'html' && name === 'svg' ? 'svg' : parentSpace
var sibling
var operator
Expand All @@ -61,7 +58,7 @@ function rule(query, config) {
pseudosToHast(query.pseudos || []),
attrsToHast(query.attrs || [])
),
!query.rule || sibling ? [] : compile(query.rule, {space: space})
!query.rule || sibling ? [] : compile(query.rule, {space})
)

return sibling ? [node, compile(query.rule, {space: parentSpace})] : node
Expand Down
29 changes: 13 additions & 16 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,27 +26,30 @@
"contributors": [
"Titus Wormer <tituswormer@gmail.com> (https://wooorm.com)"
],
"sideEffects": false,
"type": "module",
"main": "index.js",
"files": [
"index.js"
],
"dependencies": {
"css-selector-parser": "^1.3.0",
"hastscript": "^6.0.0",
"zwitch": "^1.0.0"
"css-selector-parser": "^1.0.0",
"hastscript": "^7.0.0",
"zwitch": "^2.0.0"
},
"devDependencies": {
"nyc": "^15.0.0",
"c8": "^7.0.0",
"prettier": "^2.0.0",
"remark-cli": "^9.0.0",
"remark-preset-wooorm": "^8.0.0",
"tape": "^5.0.0",
"unist-builder": "^2.0.0",
"xo": "^0.38.0"
"unist-builder": "^3.0.0",
"xo": "^0.39.0"
},
"scripts": {
"format": "remark . -qfo && prettier . -w --loglevel warn && xo --fix",
"test-api": "node test",
"test-coverage": "nyc --reporter lcov tape test.js",
"test-api": "node test.js",
"test-coverage": "c8 --check-coverage --branches 100 --functions 100 --lines 100 --statements 100 --reporter lcov node test.js",
"test": "npm run format && npm run test-coverage"
},
"prettier": {
Expand All @@ -59,17 +62,11 @@
},
"xo": {
"prettier": true,
"esnext": false,
"rules": {
"unicorn/prefer-includes": "off"
"no-var": "off",
"prefer-arrow-callback": "off"
}
},
"nyc": {
"check-coverage": true,
"lines": 100,
"functions": 100,
"branches": 100
},
"remarkConfig": {
"plugins": [
"preset-wooorm"
Expand Down
10 changes: 8 additions & 2 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@

## Install

This package is [ESM only](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c):
Node 12+ is needed to use it and it must be `import`ed instead of `require`d.

[npm][]:

```sh
Expand All @@ -21,9 +24,9 @@ npm install hast-util-from-selector
## Use

```js
var from = require('hast-util-from-selector')
import {fromSelector} from 'hast-util-from-selector'

console.log(from('p svg[viewbox=0 0 10 10] circle[cx=10][cy=10][r=10]'))
console.log(fromSelector('p svg[viewbox=0 0 10 10] circle[cx=10][cy=10][r=10]'))
```

Yields:
Expand Down Expand Up @@ -53,6 +56,9 @@ Yields:

## API

This package exports the following identifiers: `fromSelector`.
There is no default export.

### `fromSelector([selector][, options])`

Create one or more [*element*][element] [*node*][node]s from a CSS selector.
Expand Down
91 changes: 50 additions & 41 deletions test.js
Original file line number Diff line number Diff line change
@@ -1,150 +1,159 @@
'use strict'

var test = require('tape')
var h = require('hastscript')
var s = require('hastscript/svg')
var from = require('.')
import test from 'tape'
import {h, s} from 'hastscript'
import {fromSelector} from './index.js'

test('fromSelector()', function (t) {
t.equal(typeof from, 'function', 'should expose a function')

t.throws(
function () {
from('@supports (transform-origin: 5% 5%) {}')
fromSelector('@supports (transform-origin: 5% 5%) {}')
},
/Error: Rule expected but "@" found/,
'should throw w/ invalid selector'
)

t.throws(
function () {
from('a, b')
fromSelector('a, b')
},
/Error: Cannot handle selector list/,
'should throw w/ multiple selector'
)

t.throws(
function () {
from('a + b')
fromSelector('a + b')
},
/Error: Cannot handle sibling combinator `\+` at root/,
'should throw w/ next-sibling combinator at root'
)

t.throws(
function () {
from('a ~ b')
fromSelector('a ~ b')
},
/Error: Cannot handle sibling combinator `~` at root/,
'should throw w/ subsequent-sibling combinator at root'
)

t.throws(
function () {
from('[foo%=bar]')
fromSelector('[foo%=bar]')
},
/Error: Expected "=" but "%" found./,
'should throw w/ attribute modifiers'
)

t.throws(
function () {
from('[foo~=bar]')
fromSelector('[foo~=bar]')
},
/Error: Cannot handle attribute equality modifier `~=`/,
'should throw w/ attribute modifiers'
)

t.throws(
function () {
from(':active')
fromSelector(':active')
},
/Error: Cannot handle pseudo-selector `active`/,
'should throw on pseudo classes'
)

t.throws(
function () {
from(':nth-foo(2n+1)')
fromSelector(':nth-foo(2n+1)')
},
/Error: Cannot handle pseudo-selector `nth-foo`/,
'should throw on pseudo class “functions”'
)

t.throws(
function () {
from('::before')
fromSelector('::before')
},
/Error: Cannot handle pseudo-element or empty pseudo-class/,
'should throw on invalid pseudo elements'
)

t.deepEqual(from(), h(), 'should support no selector')
t.deepEqual(from(''), h(), 'should support the empty string')
t.deepEqual(from(' '), h(), 'should support whitespace only')
t.deepEqual(from('*'), h(), 'should support the universal selector')
t.deepEqual(fromSelector(), h(''), 'should support no selector')
t.deepEqual(fromSelector(''), h(''), 'should support the empty string')
t.deepEqual(fromSelector(' '), h(''), 'should support whitespace only')
t.deepEqual(fromSelector('*'), h(''), 'should support the universal selector')

t.deepEqual(
from('p i s'),
fromSelector('p i s'),
h('p', h('i', h('s'))),
'should support the descendant combinator'
)

t.deepEqual(
from('p > i > s'),
fromSelector('p > i > s'),
h('p', h('i', h('s'))),
'should support the child combinator'
)

t.deepEqual(
from('p i + s'),
fromSelector('p i + s'),
h('p', [h('i'), h('s')]),
'should support the next-sibling combinator'
)

t.deepEqual(
from('p i ~ s'),
fromSelector('p i ~ s'),
h('p', [h('i'), h('s')]),
'should support the subsequent-sibling combinator'
)

t.deepEqual(from('a'), h('a'), 'should support a tag name')
t.deepEqual(from('.a'), h('.a'), 'should support a class')
t.deepEqual(from('a.b'), h('a.b'), 'should support a tag and a class')
t.deepEqual(from('#b'), h('#b'), 'should support an id')
t.deepEqual(from('a#b'), h('a#b'), 'should support a tag and an id')
t.deepEqual(from('a#b.c.d'), h('a#b.c.d'), 'should support all together')
t.deepEqual(from('a#b#c'), h('a#c'), 'should use the last id')
t.deepEqual(from('A').tagName, 'a', 'should normalize casing')
t.deepEqual(fromSelector('a'), h('a'), 'should support a tag name')
t.deepEqual(fromSelector('.a'), h('.a'), 'should support a class')
t.deepEqual(fromSelector('a.b'), h('a.b'), 'should support a tag and a class')
t.deepEqual(fromSelector('#b'), h('#b'), 'should support an id')
t.deepEqual(fromSelector('a#b'), h('a#b'), 'should support a tag and an id')
t.deepEqual(
fromSelector('a#b.c.d'),
h('a#b.c.d'),
'should support all together'
)
t.deepEqual(fromSelector('a#b#c'), h('a#c'), 'should use the last id')
t.deepEqual(fromSelector('A').tagName, 'a', 'should normalize casing')

t.deepEqual(from('[a]'), h('', {a: true}), 'should support attributes (#1)')
t.deepEqual(from('[a=b]'), h('', {a: 'b'}), 'should support attributes (#2)')
t.deepEqual(
fromSelector('[a]'),
h('', {a: true}),
'should support attributes (#1)'
)
t.deepEqual(
fromSelector('[a=b]'),
h('', {a: 'b'}),
'should support attributes (#2)'
)

t.deepEqual(
from('.a.b[class=c]'),
fromSelector('.a.b[class=c]'),
h('.a.b.c'),
'should support class and class attributes'
)

t.deepEqual(from('altGlyph').tagName, 'altglyph', 'space (#1)')
t.deepEqual(fromSelector('altGlyph').tagName, 'altglyph', 'space (#1)')

t.deepEqual(from('altGlyph', 'svg').tagName, 'altGlyph', 'space (#2)')
t.deepEqual(fromSelector('altGlyph', 'svg').tagName, 'altGlyph', 'space (#2)')

t.deepEqual(
from('svg altGlyph').children[0].tagName,
fromSelector('svg altGlyph').children[0].tagName,
'altGlyph',
'space (#3)'
)

t.deepEqual(
from('div svg + altGlyph').children[1].tagName,
fromSelector('div svg + altGlyph').children[1].tagName,
'altglyph',
'space (#4)'
)

t.deepEqual(
from('p svg[viewbox=0 0 10 10] circle[cx=10][cy=10][r=10] altGlyph'),
fromSelector(
'p svg[viewbox=0 0 10 10] circle[cx=10][cy=10][r=10] altGlyph'
),
h('p', [
s('svg', {viewBox: '0 0 10 10'}, [
s('circle', {cx: '10', cy: '10', r: '10'}, [s('altGlyph')])
Expand Down

0 comments on commit 5573ee1

Please sign in to comment.