Comparing version 1.0.0 to 1.0.1
@@ -1,30 +0,7 @@ | ||
declare type QueryData = { | ||
[property: string]: Text | Attr | Html | List<any>; | ||
}; | ||
declare type Text = { | ||
type: "TEXT"; | ||
result: string; | ||
selector: string; | ||
}; | ||
declare type Attr = { | ||
type: "ATTR"; | ||
result: string; | ||
attribute: string; | ||
selector: string; | ||
}; | ||
declare type List<T extends object> = { | ||
type: "LIST"; | ||
result: Array<T>; | ||
selector: string; | ||
data: QueryData; | ||
}; | ||
declare type Html = { | ||
type: "HTML"; | ||
result: string; | ||
selector: string; | ||
}; | ||
import { Attr, Html, List, Text, QueryData, Exists } from "./type"; | ||
declare type GetTypeFromQuery<Q extends QueryData> = { | ||
[P in keyof Q]: Q[P]["result"]; | ||
[P in keyof Q]: Q[P]["convert"] extends (data: string) => infer R ? R : Q[P]["convert"]; | ||
}; | ||
export declare const scrap: <Q extends QueryData>(html: string, query: Q) => GetTypeFromQuery<Q>; | ||
declare type DefaultFn = (data: string) => string; | ||
export declare const Q: { | ||
@@ -35,3 +12,3 @@ /** | ||
*/ | ||
text: (selector: string) => Text; | ||
text: (selector: string) => Text<DefaultFn>; | ||
/** | ||
@@ -42,3 +19,3 @@ * Get html attribute | ||
*/ | ||
attr: (selector: string, attribute: string) => Attr; | ||
attr: (selector: string, attribute: string) => Attr<DefaultFn>; | ||
/** | ||
@@ -48,4 +25,9 @@ * Get html content | ||
*/ | ||
html: (selector: string) => Html; | ||
html: (selector: string) => Html<DefaultFn>; | ||
/** | ||
* Check if element exists | ||
* @param selector - css selector | ||
*/ | ||
exists: (selector: string) => Exists; | ||
/** | ||
* Get list of items | ||
@@ -52,0 +34,0 @@ * @param selector - css selector for list of items |
@@ -11,3 +11,3 @@ "use strict"; | ||
if (val.selector === "") { | ||
// Get text from root item | ||
// Get text from root element | ||
ref[prop] = $(context).text(); | ||
@@ -23,2 +23,3 @@ } | ||
if (val.selector === "") { | ||
// Get attribute from root element | ||
ref[prop] = $(context).attr(val.attribute); | ||
@@ -34,2 +35,3 @@ } | ||
if (val.selector === "") { | ||
// Get html from root element | ||
ref[prop] = $(context).html(); | ||
@@ -43,2 +45,8 @@ } | ||
} | ||
case "EXISTS": { | ||
// TODO: selector cannot be "" | ||
var el = $(val.selector, context); | ||
ref[prop] = el.length > 0 ? true : false; | ||
break; | ||
} | ||
case "LIST": { | ||
@@ -72,3 +80,7 @@ var result = []; | ||
*/ | ||
text: function (selector) { return ({ type: "TEXT", selector: selector, result: "" }); }, | ||
text: function (selector) { return ({ | ||
type: "TEXT", | ||
selector: selector, | ||
convert: function (data) { return data; } | ||
}); }, | ||
/** | ||
@@ -82,3 +94,3 @@ * Get html attribute | ||
selector: selector, | ||
result: "", | ||
convert: function (data) { return data; }, | ||
attribute: attribute | ||
@@ -91,7 +103,16 @@ }); }, | ||
html: function (selector) { return ({ | ||
type: 'HTML', | ||
type: "HTML", | ||
selector: selector, | ||
result: "" | ||
convert: function (data) { return data; } | ||
}); }, | ||
/** | ||
* Check if element exists | ||
* @param selector - css selector | ||
*/ | ||
exists: function (selector) { return ({ | ||
type: "EXISTS", | ||
selector: selector, | ||
convert: true | ||
}); }, | ||
/** | ||
* Get list of items | ||
@@ -101,3 +122,3 @@ * @param selector - css selector for list of items | ||
*/ | ||
list: function (selector, data) { return ({ type: "LIST", result: [], selector: selector, data: data }); } | ||
list: function (selector, data) { return ({ type: "LIST", convert: [], selector: selector, data: data }); } | ||
}; |
import { load } from "cheerio"; | ||
import { Attr, Html, List, Text, QueryData, Exists } from "./type"; | ||
type QueryData = { | ||
[property: string]: Text | Attr | Html | List<any>; | ||
}; | ||
type Query = QueryData; | ||
type Text = { | ||
// --- Internal --- | ||
type: "TEXT"; | ||
result: string; | ||
// ---Additional--- | ||
selector: string; | ||
type GetTypeFromQuery<Q extends QueryData> = { | ||
[P in keyof Q]: Q[P]["convert"] extends (data: string) => infer R | ||
? R | ||
:Q[P]["convert"] | ||
}; | ||
type Attr = { | ||
type: "ATTR"; | ||
result: string; | ||
attribute: string; | ||
selector: string; | ||
}; | ||
type List<T extends object> = { | ||
// --- Internal --- | ||
type: "LIST"; | ||
result: Array<T>; | ||
// ---Additional--- | ||
selector: string; | ||
data: QueryData; | ||
}; | ||
type Html = { | ||
// --- Internal --- | ||
type: "HTML"; | ||
result: string; | ||
// ---Additional--- | ||
selector: string; | ||
}; | ||
type Query = QueryData; | ||
type GetTypeFromQuery<Q extends QueryData> = { [P in keyof Q]: Q[P]["result"] }; | ||
const scrapObject = <Q extends QueryData>( | ||
@@ -54,3 +22,3 @@ $: CheerioStatic, | ||
if (val.selector === "") { | ||
// Get text from root item | ||
// Get text from root element | ||
ref[prop] = $(context).text(); | ||
@@ -65,2 +33,3 @@ } else { | ||
if (val.selector === "") { | ||
// Get attribute from root element | ||
ref[prop] = $(context).attr(val.attribute); | ||
@@ -75,2 +44,3 @@ } else { | ||
if (val.selector === "") { | ||
// Get html from root element | ||
ref[prop] = $(context).html(); | ||
@@ -82,3 +52,9 @@ } else { | ||
break; | ||
} | ||
} | ||
case "EXISTS": { | ||
// TODO: selector cannot be "" | ||
const el = $(val.selector, context); | ||
ref[prop] = el.length > 0 ? true : false; | ||
break; | ||
} | ||
case "LIST": { | ||
@@ -112,2 +88,3 @@ const result: GetTypeFromQuery<typeof val.data>[] = []; | ||
type DefaultFn = (data: string) => string; | ||
export const Q = { | ||
@@ -118,3 +95,7 @@ /** | ||
*/ | ||
text: (selector: string): Text => ({ type: "TEXT", selector, result: "" }), | ||
text: (selector: string): Text<DefaultFn> => ({ | ||
type: "TEXT", | ||
selector, | ||
convert: (data) => data | ||
}), | ||
@@ -126,9 +107,9 @@ /** | ||
*/ | ||
attr: (selector: string, attribute: string): Attr => ({ | ||
attr: (selector: string, attribute: string): Attr<DefaultFn> => ({ | ||
type: "ATTR", | ||
selector, | ||
result: "", | ||
convert: (data) => data, | ||
attribute | ||
}), | ||
/** | ||
@@ -138,9 +119,19 @@ * Get html content | ||
*/ | ||
html: (selector: string): Html => ({ | ||
type: 'HTML', | ||
html: (selector: string): Html<DefaultFn> => ({ | ||
type: "HTML", | ||
selector, | ||
result: "" | ||
}), | ||
convert: (data) => data | ||
}), | ||
/** | ||
* Check if element exists | ||
* @param selector - css selector | ||
*/ | ||
exists: (selector: string): Exists => ({ | ||
type: "EXISTS", | ||
selector, | ||
convert: true | ||
}), | ||
/** | ||
* Get list of items | ||
@@ -153,3 +144,3 @@ * @param selector - css selector for list of items | ||
data: Q | ||
): List<GetTypeFromQuery<Q>> => ({ type: "LIST", result: [], selector, data }) | ||
): List<GetTypeFromQuery<Q>> => ({ type: "LIST", convert: [], selector, data }) | ||
}; |
{ | ||
"name": "scrapq", | ||
"version": "1.0.0", | ||
"version": "1.0.1", | ||
"description": "Lightweight Typescript library for scrapping html", | ||
@@ -29,3 +29,3 @@ "main": "./dist/Index.js", | ||
"prettier": "^1.13.7", | ||
"typescript": "^2.9.2" | ||
"typescript": "^3.1.0-dev.20180721" | ||
}, | ||
@@ -32,0 +32,0 @@ "dependencies": { |
@@ -7,3 +7,3 @@ # ScrapQ | ||
Lightweight Typescript library for scrapping html. | ||
Lightweight Typescript library for scrapping html with **type inference**. | ||
@@ -13,4 +13,4 @@ ## About | ||
There are plenty scrapping libs out there, but only few with full Typescript support - Typescript will infer type based | ||
on your query. This is small library with only one purpuse to provide scrapping in human readable format with full | ||
Typescript support like intellisense. | ||
on your query. This is small library with only one purpose to provide scrapping in human readable format with full | ||
Typescript support like intellisense and type inference. | ||
@@ -93,3 +93,2 @@ ## Examples | ||
`Q.attr(selector: string, htmlAttribute: string)` | ||
@@ -103,4 +102,8 @@ | ||
`Q.exists(selector: string)` | ||
get `true/false` if element exists | ||
`Q.list(selector: string, query: Query)` | ||
get list of items |
@@ -7,3 +7,3 @@ import { scrap, Q } from '../lib/Index'; | ||
<li><span>Guten Tag</span></li> | ||
<li><span>Ciao</span></li> | ||
<li><span class="msg">Ciao</span></li> | ||
<li><span>Bonjour</span></li> | ||
@@ -18,10 +18,10 @@ </ul> | ||
title: Q.text('h1.title') | ||
}); | ||
}); | ||
expect(result).toEqual({ title: 'Hello'}); | ||
}); | ||
it('should scrap attributes from <h1/>', () => { | ||
const result = scrap(STR_TO_SCRAP, { | ||
title: Q.attr('h1.title', 'class') | ||
}); | ||
}); | ||
expect(result).toEqual({ title: 'title'}); | ||
@@ -40,2 +40,28 @@ }); | ||
it('should exists .title', () => { | ||
const result = scrap(STR_TO_SCRAP, { | ||
hasTitle: Q.exists('h1.title') | ||
}); | ||
expect(result.hasTitle).toBe(true); | ||
}); | ||
it('should not exists .castle', () => { | ||
const result = scrap(STR_TO_SCRAP, { | ||
hasCastle: Q.exists('.castle') | ||
}); | ||
expect(result.hasCastle).toBe(false); | ||
}); | ||
it('should exists .msg inside list', () => { | ||
const result = scrap(STR_TO_SCRAP, { | ||
items: Q.list('li', { | ||
hasMsg: Q.exists('span.msg') | ||
}) | ||
}); | ||
expect(result.items.length).toBe(3); | ||
expect(result.items[0].hasMsg).toBe(false); | ||
expect(result.items[1].hasMsg).toBe(true); | ||
expect(result.items[2].hasMsg).toBe(false); | ||
}); | ||
it('should scrap text from <li><span/>', () => { | ||
@@ -42,0 +68,0 @@ const result = scrap(STR_TO_SCRAP, { |
@@ -0,0 +0,0 @@ { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
21020
13
486
106