-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
15 changed files
with
1,503 additions
and
572 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,16 @@ | ||
{ | ||
"presets": [ | ||
[ "@babel/env", { | ||
"modules": false | ||
} ] | ||
"@babel/preset-typescript", | ||
[ | ||
"@babel/env", | ||
{ | ||
"modules": false | ||
} | ||
] | ||
], | ||
"env": { | ||
"test": { | ||
"presets": [ "@babel/env" ] | ||
"presets": ["@babel/preset-typescript", "@babel/env"] | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,12 @@ | ||
{ | ||
"root": true, | ||
"extends": ["eslint:recommended", "prettier"], | ||
"plugins": ["prettier"], | ||
"parserOptions": { | ||
"ecmaVersion": 2020, | ||
"sourceType": "module" | ||
}, | ||
"extends": "@aduth/eslint-config", | ||
"env": { | ||
"es6": true, | ||
"browser": true, | ||
"mocha": true, | ||
"node": true | ||
}, | ||
"rules": { | ||
"prettier/prettier": "error" | ||
"no-redeclare": "off", | ||
"@typescript-eslint/no-redeclare": "error" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,4 @@ | ||
/es/* | ||
!/es/index.d.ts | ||
es/ | ||
node_modules/ | ||
*.log | ||
dist/ |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import register from '@babel/register'; | ||
|
||
register({ extensions: ['.ts'] }); |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,212 @@ | ||
/** | ||
* Internal dependencies | ||
*/ | ||
import getPath from './get-path'; | ||
|
||
/** | ||
* Function returning a DOM document created by `createHTMLDocument`. The same | ||
* document is returned between invocations. | ||
* | ||
* @return DOM document. | ||
*/ | ||
const getDocument = (() => { | ||
let doc: Document; | ||
return (): Document => { | ||
if (!doc) { | ||
doc = document.implementation.createHTMLDocument(''); | ||
} | ||
|
||
return doc; | ||
}; | ||
})(); | ||
|
||
type MatcherFn<R = any> = (node: Element) => R; | ||
|
||
type MatcherObj = { [x: string]: MatcherObj | MatcherFn }; | ||
|
||
type MatcherObjResult<F extends MatcherFn, O extends MatcherObj> = { | ||
[K in keyof O]: O[K] extends F | ||
? ReturnType<O[K]> | ||
: O[K] extends MatcherObj | ||
? MatcherObjResult<F, O[K]> | ||
: never; | ||
}; | ||
|
||
/** | ||
* Given a markup string or DOM element, creates an object aligning with the | ||
* shape of the matchers object, or the value returned by the matcher. | ||
* | ||
* @param source Source content | ||
* @param matchers Object of matchers | ||
* @return Matched values, shaped by object | ||
*/ | ||
export function parse<F extends MatcherFn, O extends MatcherObj>( | ||
source: string | Element, | ||
matchers: O | ||
): MatcherObjResult<F, O>; | ||
|
||
/** | ||
* Given a markup string or DOM element, creates an object aligning with the | ||
* shape of the matchers object, or the value returned by the matcher. | ||
* | ||
* @param source Source content | ||
* @param matcher Matcher function | ||
* @return Matched value | ||
*/ | ||
export function parse<F extends MatcherFn>(source: string | Element, matchers: F): ReturnType<F>; | ||
|
||
/** | ||
* Given a markup string or DOM element, creates an object aligning with the | ||
* shape of the matchers object, or the value returned by the matcher. | ||
* | ||
* @param source Source content | ||
* @param matchers Matcher function or object of matchers | ||
*/ | ||
export function parse<F extends MatcherFn, O extends MatcherObj>( | ||
source: string | Element, | ||
matchers: O | F | ||
): MatcherObjResult<F, O> | ReturnType<F>; | ||
|
||
/** | ||
* Given a markup string or DOM element, creates an object aligning with the | ||
* shape of the matchers object, or the value returned by the matcher. | ||
* | ||
* @param source Source content | ||
* @param matchers Matcher function or object of matchers | ||
*/ | ||
export function parse(source: string | Element, matchers?: undefined): undefined; | ||
|
||
/** | ||
* Given a markup string or DOM element, creates an object aligning with the | ||
* shape of the matchers object, or the value returned by the matcher. | ||
* | ||
* @param source Source content | ||
* @param matchers Matcher function or object of matchers | ||
*/ | ||
export function parse<F extends MatcherFn, O extends MatcherObj>( | ||
source: string | Element, | ||
matchers?: O | F | ||
) { | ||
if (!matchers) { | ||
return; | ||
} | ||
|
||
// Coerce to element | ||
if ('string' === typeof source) { | ||
const doc = getDocument(); | ||
doc.body.innerHTML = source; | ||
source = doc.body; | ||
} | ||
|
||
// Return singular value | ||
if ('function' === typeof matchers) { | ||
return matchers(source); | ||
} | ||
|
||
// Bail if we can't handle matchers | ||
if (Object !== matchers.constructor) { | ||
return; | ||
} | ||
|
||
// Shape result by matcher object | ||
return Object.keys(matchers).reduce((memo: MatcherObj, key) => { | ||
const inner = matchers[key]; | ||
memo[key] = parse(source, inner); | ||
return memo; | ||
}, {}); | ||
} | ||
|
||
/** | ||
* Generates a function which matches node of type selector, returning an | ||
* attribute by property if the attribute exists. If no selector is passed, | ||
* returns property of the query element. | ||
* | ||
* @param selector Optional selector | ||
* @param name Property name | ||
* @return Matcher function returning the property value | ||
*/ | ||
export function prop<N extends keyof Element>(selector?: string, name?: N): MatcherFn<Element[N]> { | ||
if (1 === arguments.length) { | ||
name = selector as N; | ||
selector = undefined; | ||
} | ||
|
||
return function (node) { | ||
let match: Element | null = node; | ||
if (selector) { | ||
match = node.querySelector(selector); | ||
} | ||
|
||
if (match) { | ||
return getPath(match, name!); | ||
} | ||
}; | ||
} | ||
|
||
/** | ||
* Generates a function which matches node of type selector, returning an | ||
* attribute by name if the attribute exists. If no selector is passed, | ||
* returns attribute of the query element. | ||
* | ||
* @param selector Optional selector | ||
* @param name Attribute name | ||
* @return Matcher function returning the attribute value | ||
*/ | ||
export function attr(selector?: string, name?: string): MatcherFn<string | undefined> { | ||
if (1 === arguments.length) { | ||
name = selector; | ||
selector = undefined; | ||
} | ||
|
||
return function (node) { | ||
const attributes = prop(selector, 'attributes')(node); | ||
if (attributes && Object.prototype.hasOwnProperty.call(attributes, name!)) { | ||
return attributes.getNamedItem(name!)!.value; | ||
} | ||
}; | ||
} | ||
|
||
/** | ||
* Convenience for `prop( selector, 'innerHTML' )`. | ||
* | ||
* @see prop() | ||
* | ||
* @param selector Optional selector | ||
* @return Matcher which returns innerHTML | ||
*/ | ||
export function html(selector?: string): MatcherFn<string> { | ||
return prop(selector, 'innerHTML') as MatcherFn<string>; | ||
} | ||
|
||
/** | ||
* Convenience for `prop( selector, 'textContent' )`. | ||
* | ||
* @see prop() | ||
* | ||
* @param selector Optional selector | ||
* @return Matcher which returns text content | ||
*/ | ||
export function text(selector?: string): MatcherFn<string> { | ||
return prop(selector, 'textContent') as MatcherFn<string>; | ||
} | ||
|
||
/** | ||
* Creates a new matching context by first finding elements matching selector | ||
* using querySelectorAll before then running another `parse` on `matchers` | ||
* scoped to the matched elements. | ||
* | ||
* @see parse() | ||
* | ||
* @param {string} selector Selector to match | ||
* @param {Matcher<T>} matchers Matcher function or object of matchers | ||
* @return Matcher function which returns an array of matched value(s) | ||
*/ | ||
export function query<F extends MatcherFn, O extends MatcherObj>( | ||
selector: string, | ||
matchers?: F | O | ||
): MatcherFn<MatcherObjResult<F, O>[]> { | ||
return function (node) { | ||
const matches = node.querySelectorAll(selector); | ||
return [].map.call(matches, (match) => parse(match, matchers!)) as MatcherObjResult<F, O>[]; | ||
}; | ||
} |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
{ | ||
"extends": "./tsconfig.json", | ||
"compilerOptions": { | ||
"declaration": true, | ||
"emitDeclarationOnly": true, | ||
"outDir": "./es", | ||
"rootDir": "src", | ||
"noEmit": false | ||
}, | ||
"include": ["src"] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,10 @@ | ||
{ | ||
"compilerOptions": { | ||
"target": "ES2017", | ||
"lib": ["ES2017", "DOM", "DOM.Iterable"], | ||
"outDir": "./es", | ||
"strict": true, | ||
"allowJs": true, | ||
"checkJs": true, | ||
"declaration": true, | ||
"emitDeclarationOnly": true | ||
}, | ||
"include": ["src/**/*.js"] | ||
"compilerOptions": { | ||
"target": "ES2017", | ||
"lib": ["ES2017", "DOM", "DOM.Iterable"], | ||
"moduleResolution": "node", | ||
"strict": true, | ||
"noEmit": true | ||
}, | ||
"include": ["src", "test"] | ||
} |