1- import { getElement , getElementMatches , getElements } from '../utils.js' // Assuming you have imported the address comparison function
1+ import {
2+ cleanArray ,
3+ getElement ,
4+ getElementMatches ,
5+ getElements
6+ } from '../utils.js' // Assuming you have imported the address comparison function
27import { ErrorResponse , ProfileResult , SuccessResponse } from '../types.js'
38import { isSameAge } from '../comparisons/is-same-age.js'
49import { isSameName } from '../comparisons/is-same-name.js'
@@ -72,7 +77,12 @@ export function extractProfiles (action, userData, root = document) {
7277
7378 return {
7479 results : profilesElementList . map ( ( element ) => {
75- const scrapedData = createProfile ( element , action . profile )
80+ const elementFactory = ( key , value ) => {
81+ return value ?. findElements
82+ ? cleanArray ( getElements ( element , value . selector ) )
83+ : cleanArray ( getElement ( element , value . selector ) || getElementMatches ( element , value . selector ) )
84+ }
85+ const scrapedData = createProfile ( elementFactory , action . profile )
7686 const { result, score, matchedFields } = scrapedDataMatchesUserData ( userData , scrapedData )
7787 return new ProfileResult ( {
7888 scrapedData,
@@ -105,37 +115,40 @@ export function extractProfiles (action, userData, root = document) {
105115 * "profileUrl": "https://example.com/1234"
106116 * }
107117 *
108- * @param {HTMLElement } profileElement
118+ * @param {(key: string, value: ExtractProfileProperty) => {innerText: string}[] } elementFactory
119+ * a function that produces elements for a given key + ExtractProfileProperty
109120 * @param {Record<string, ExtractProfileProperty> } extractData
110121 * @return {Record<string, any> }
111122 */
112- function createProfile ( profileElement , extractData ) {
123+ export function createProfile ( elementFactory , extractData ) {
113124 const output = { }
114125 for ( const [ key , value ] of Object . entries ( extractData ) ) {
115126 if ( ! value ?. selector ) {
116127 output [ key ] = null
117128 } else {
129+ const elements = elementFactory ( key , value )
118130 const evaluatedValue = value ?. findElements
119- ? findFromElements ( profileElement , key , value )
120- : findFromElement ( profileElement , key , value )
131+ ? findFromElements ( elements , key , value )
132+ : findFromElement ( elements [ 0 ] , key , value )
121133
122134 // Note: This can return a string, string[], or null
123135 const extractedValue = extractValue ( key , value , evaluatedValue )
124136
125- // try to use the extracted value first, then the originally evaluated, falling back to null
126- output [ key ] = extractedValue || evaluatedValue || null
137+ // try to use the extracted value, or fall back to null
138+ // this allows 'extractValue' to return null|undefined
139+ output [ key ] = extractedValue || null
127140 }
128141 }
129142 return output
130143}
131144
132145/**
133- * @param {HTMLElement } profileElement
146+ * @param {{innerText: string}[] } elements
134147 * @param {string } key
135148 * @param {ExtractProfileProperty } extractField
149+ * @return {string[] }
136150 */
137- function findFromElements ( profileElement , key , extractField ) {
138- const elements = getElements ( profileElement , extractField . selector ) || null
151+ function findFromElements ( elements , key , extractField ) {
139152 const elementValues = [ ]
140153 if ( elements ) {
141154 for ( const element of elements ) {
@@ -153,15 +166,12 @@ function findFromElements (profileElement, key, extractField) {
153166}
154167
155168/**
156- * @param {HTMLElement } profileElement
169+ * @param {{innerText: string} } element
157170 * @param {string } dataKey - such as 'name', 'age' etc
158171 * @param {ExtractProfileProperty } extractField
159172 * @return {string }
160173 */
161- function findFromElement ( profileElement , dataKey , extractField ) {
162- const element = getElement ( profileElement , extractField . selector ) ||
163- getElementMatches ( profileElement , extractField . selector )
164-
174+ function findFromElement ( element , dataKey , extractField ) {
165175 // todo: should we use textContent here?
166176 let elementValue = rules [ dataKey ] ?. ( element ) ?? element ?. innerText ?? null
167177
@@ -282,7 +292,7 @@ export function aggregateFields (profile) {
282292 * @param {string } key
283293 * @param {ExtractProfileProperty } value
284294 * @param {string | string[] } elementValue
285- * @return {string|string[]|null }
295+ * @return {string|string[]|null|undefined }
286296 */
287297export function extractValue ( key , value , elementValue ) {
288298 if ( ! elementValue ) return null
0 commit comments