-
Notifications
You must be signed in to change notification settings - Fork 0
/
html-to-courses.ts
66 lines (57 loc) · 1.9 KB
/
html-to-courses.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
import { DOMParser } from "https://deno.land/x/deno_dom@v0.1.48/deno-dom-wasm.ts";
import { z } from "https://deno.land/x/zod@v3.23.8/mod.ts";
export const course = z.object({
id: z.string(),
name: z.string(),
city: z.string().trim(),
state: z.string(),
zip: z.string().optional(),
holeCount: z.coerce.number(),
rating: z.coerce.number().optional(),
yearEstablished: z.coerce.number(),
page: z.number().optional(),
});
export type Course = z.infer<typeof course>;
export interface ExtractCoursesResponse {
courses: Course[];
hasMore: boolean;
totalCourses?: string;
}
export function extractCoursesFromHtml(html: string): ExtractCoursesResponse {
const $ = new DOMParser().parseFromString(html, "text/html");
const rows = $.querySelectorAll("tbody tr");
const courses: Course[] = [];
[...rows].forEach((el) => {
const id = el.querySelector(".views-field-title a")?.getAttribute("href");
const zip = el.querySelector(".views-field-field-course-location-1")
?.textContent
.replace(/\s/g, "");
courses.push(
course.parse({
id,
yearEstablished: el.querySelector(
".views-field-field-course-year-established",
)
?.textContent,
name: el.querySelector(".views-field-title a")?.textContent,
city: el
.querySelector(".views-field-field-course-location")?.textContent
.replace(/\n/, ""),
state: el.querySelector(".addressfield-state")?.textContent,
zip: zip,
holeCount: el.querySelector(".views-field-field-course-holes")
?.textContent,
rating: el
.querySelector(".average-rating")
?.textContent
.replace(/Average: /, ""),
}),
);
});
return {
courses,
hasMore: $.querySelectorAll(".pager-last.last").length > 0,
totalCourses: $.querySelector(".view-footer")?.textContent.trim().split(" ")
.pop(),
};
}