Skip to content

Commit 3a672ff

Browse files
authored
refactor(feedhandler): Move logic of FeedHandler to function (#912)
1 parent 39a8109 commit 3a672ff

File tree

2 files changed

+92
-87
lines changed

2 files changed

+92
-87
lines changed

src/FeedHandler.ts

Lines changed: 91 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ interface Feed {
5353
items?: FeedItem[];
5454
}
5555

56-
// TODO: Consume data as it is coming in
56+
/** @deprecated Handler is no longer necessary; use `getFeed` or `parseFeed` instead. */
5757
export class FeedHandler extends DomHandler {
5858
feed?: Feed;
5959

@@ -74,103 +74,108 @@ export class FeedHandler extends DomHandler {
7474
}
7575

7676
onend(): void {
77-
const feedRoot = getOneElement(isValidFeed, this.dom);
77+
const feed = getFeed(this.dom);
7878

79-
if (!feedRoot) {
79+
if (feed) {
80+
this.feed = feed;
81+
this.handleCallback(null);
82+
} else {
8083
this.handleCallback(new Error("couldn't find root of feed"));
81-
return;
8284
}
85+
}
86+
}
87+
88+
/**
89+
* Get the feed object from the root of a DOM tree.
90+
*
91+
* @param dom - The DOM to to extract the feed from.
92+
* @returns The feed.
93+
*/
94+
export function getFeed(dom: Node[]): Feed | null {
95+
const feedRoot = getOneElement(isValidFeed, dom);
96+
97+
if (!feedRoot) return null;
98+
99+
const feed: Feed = {};
100+
101+
if (feedRoot.name === "feed") {
102+
const childs = feedRoot.children;
103+
feed.type = "atom";
104+
addConditionally(feed, "id", "id", childs);
105+
addConditionally(feed, "title", "title", childs);
106+
const href = getAttribute("href", getOneElement("link", childs));
107+
if (href) {
108+
feed.link = href;
109+
}
110+
addConditionally(feed, "description", "subtitle", childs);
111+
112+
const updated = fetch("updated", childs);
113+
if (updated) {
114+
feed.updated = new Date(updated);
115+
}
116+
117+
addConditionally(feed, "author", "email", childs, true);
118+
feed.items = getElements("entry", childs).map((item) => {
119+
const entry: FeedItem = {};
120+
const { children } = item;
83121

84-
const feed: Feed = {};
122+
addConditionally(entry, "id", "id", children);
123+
addConditionally(entry, "title", "title", children);
85124

86-
if (feedRoot.name === "feed") {
87-
const childs = feedRoot.children;
88-
feed.type = "atom";
89-
addConditionally(feed, "id", "id", childs);
90-
addConditionally(feed, "title", "title", childs);
91-
const href = getAttribute("href", getOneElement("link", childs));
125+
const href = getAttribute("href", getOneElement("link", children));
92126
if (href) {
93-
feed.link = href;
127+
entry.link = href;
94128
}
95-
addConditionally(feed, "description", "subtitle", childs);
96129

97-
const updated = fetch("updated", childs);
98-
if (updated) {
99-
feed.updated = new Date(updated);
130+
const description =
131+
fetch("summary", children) || fetch("content", children);
132+
if (description) {
133+
entry.description = description;
100134
}
101135

102-
addConditionally(feed, "author", "email", childs, true);
103-
feed.items = getElements("entry", childs).map((item) => {
104-
const entry: FeedItem = {};
105-
const { children } = item;
106-
107-
addConditionally(entry, "id", "id", children);
108-
addConditionally(entry, "title", "title", children);
136+
const pubDate = fetch("updated", children);
137+
if (pubDate) {
138+
entry.pubDate = new Date(pubDate);
139+
}
109140

110-
const href = getAttribute(
111-
"href",
112-
getOneElement("link", children)
113-
);
114-
if (href) {
115-
entry.link = href;
116-
}
117-
118-
const description =
119-
fetch("summary", children) || fetch("content", children);
120-
if (description) {
121-
entry.description = description;
122-
}
123-
124-
const pubDate = fetch("updated", children);
125-
if (pubDate) {
126-
entry.pubDate = new Date(pubDate);
127-
}
141+
entry.media = getMediaElements(children);
128142

129-
entry.media = getMediaElements(children);
143+
return entry;
144+
});
145+
} else {
146+
const childs =
147+
getOneElement("channel", feedRoot.children)?.children ?? [];
148+
feed.type = feedRoot.name.substr(0, 3);
149+
feed.id = "";
130150

131-
return entry;
132-
});
133-
} else {
134-
const childs =
135-
getOneElement("channel", feedRoot.children)?.children ?? [];
136-
feed.type = feedRoot.name.substr(0, 3);
137-
feed.id = "";
138-
139-
addConditionally(feed, "title", "title", childs);
140-
addConditionally(feed, "link", "link", childs);
141-
addConditionally(feed, "description", "description", childs);
142-
143-
const updated = fetch("lastBuildDate", childs);
144-
if (updated) {
145-
feed.updated = new Date(updated);
146-
}
151+
addConditionally(feed, "title", "title", childs);
152+
addConditionally(feed, "link", "link", childs);
153+
addConditionally(feed, "description", "description", childs);
147154

148-
addConditionally(feed, "author", "managingEditor", childs, true);
149-
150-
feed.items = getElements("item", feedRoot.children).map(
151-
(item: Element) => {
152-
const entry: FeedItem = {};
153-
const { children } = item;
154-
addConditionally(entry, "id", "guid", children);
155-
addConditionally(entry, "title", "title", children);
156-
addConditionally(entry, "link", "link", children);
157-
addConditionally(
158-
entry,
159-
"description",
160-
"description",
161-
children
162-
);
163-
const pubDate = fetch("pubDate", children);
164-
if (pubDate) entry.pubDate = new Date(pubDate);
165-
entry.media = getMediaElements(children);
166-
return entry;
167-
}
168-
);
155+
const updated = fetch("lastBuildDate", childs);
156+
if (updated) {
157+
feed.updated = new Date(updated);
169158
}
170159

171-
this.feed = feed;
172-
this.handleCallback(null);
160+
addConditionally(feed, "author", "managingEditor", childs, true);
161+
162+
feed.items = getElements("item", feedRoot.children).map(
163+
(item: Element) => {
164+
const entry: FeedItem = {};
165+
const { children } = item;
166+
addConditionally(entry, "id", "guid", children);
167+
addConditionally(entry, "title", "title", children);
168+
addConditionally(entry, "link", "link", children);
169+
addConditionally(entry, "description", "description", children);
170+
const pubDate = fetch("pubDate", children);
171+
if (pubDate) entry.pubDate = new Date(pubDate);
172+
entry.media = getMediaElements(children);
173+
return entry;
174+
}
175+
);
173176
}
177+
178+
return feed;
174179
}
175180

176181
function getMediaElements(where: Node | Node[]): FeedItemMedia[] {
@@ -234,7 +239,7 @@ function getOneElement(
234239
return DomUtils.getElementsByTagName(tagName, node, true, 1)[0];
235240
}
236241
function fetch(tagName: string, where: Node | Node[], recurse = false): string {
237-
return DomUtils.getText(
242+
return DomUtils.textContent(
238243
DomUtils.getElementsByTagName(tagName, where, recurse, 1)
239244
).trim();
240245
}
@@ -267,13 +272,13 @@ function isValidFeed(value: string) {
267272
* Parse a feed.
268273
*
269274
* @param feed The feed that should be parsed, as a string.
270-
* @param options Optionally, options for parsing. When using this option, you should set `xmlMode` to `true`.
275+
* @param options Optionally, options for parsing. When using this, you should set `xmlMode` to `true`.
271276
*/
272277
export function parseFeed(
273278
feed: string,
274279
options: ParserOptions & DomHandlerOptions = { xmlMode: true }
275-
): Feed | undefined {
276-
const handler = new FeedHandler(options);
280+
): Feed | null {
281+
const handler = new DomHandler(null, options);
277282
new Parser(handler, options).end(feed);
278-
return handler.feed;
283+
return getFeed(handler.dom);
279284
}

src/__fixtures__/test-helper.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ interface TestFile {
122122
* @param getResult Function to be called with the actual results.
123123
*/
124124
export function createSuite(
125-
name: string,
125+
name: "Events" | "Feeds" | "Stream",
126126
getResult: (
127127
file: TestFile,
128128
done: (error: Error | null, actual?: unknown | unknown[]) => void

0 commit comments

Comments
 (0)