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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
/**
* Copyright (C) 2018 Noah Loomans
*
* This file is part of rooster.hetmml.nl.
*
* rooster.hetmml.nl is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* rooster.hetmml.nl is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with rooster.hetmml.nl. If not, see <http://www.gnu.org/licenses/>.
*
*/
const { JSDOM } = require('jsdom');
function fixFirstLargeScheduleItem(trNodeList) {
return Array.from(trNodeList).some((trNode, timeOfDay) => {
const tdNodeList = trNode.children;
return Array.from(tdNodeList).some((tdNode, dayOfWeek) => {
const height = tdNode.rowSpan / 2;
if (height === 1) {
return false;
}
tdNode.rowSpan = 2; // eslint-disable-line no-param-reassign
for (let i = 1; i < height; i += 1) {
// Are we at the end of the table?
if (dayOfWeek === 4) {
// If so, we cannot use insertBefore, because the is no node to insert
// it before. Use appendChild instead.
trNodeList[timeOfDay + i].appendChild(tdNode.cloneNode(true));
} else {
trNodeList[timeOfDay + i]
.insertBefore(
tdNode.cloneNode(true),
trNodeList[timeOfDay + i].children[dayOfWeek],
);
}
}
return true;
});
});
}
function parseSchedule(axiosResponse) {
const dom = new JSDOM(axiosResponse.data);
const { window } = dom;
const { document } = window;
const tableNode = document.querySelector('center > table');
const tbodyNode = tableNode.querySelector('tbody');
const trNodeList = tbodyNode.children;
Array.from(trNodeList).forEach((trNode, timeOfDay) => {
const tdNodeList = trNode.children;
if (timeOfDay === 0 || trNode.children.length === 0) {
tbodyNode.removeChild(trNode);
return;
}
Array.from(tdNodeList).forEach((tdNode, dayOfWeek) => {
if (dayOfWeek === 0) {
trNode.removeChild(tdNode);
}
});
});
let shouldContinue = true;
while (shouldContinue) {
shouldContinue = fixFirstLargeScheduleItem(trNodeList);
}
const scheduleItems = [];
Array.from(trNodeList).forEach((trNode, timeOfDay) => {
const tdNodeList = trNode.children;
Array.from(tdNodeList).forEach((tdNode, dayOfWeek) => {
if (tdNode.textContent.trim() === '') {
return;
}
const childTableNode = tdNode.querySelector('table');
const childTrNodeList = childTableNode.querySelectorAll('tr');
Array.from(childTrNodeList).forEach((childTrNode) => {
const subject = childTrNode.children[0].textContent.trim();
const attendees = childTrNode.children[1]
? childTrNode.children[1].textContent.trim()
: undefined;
const location = childTrNode.children[2]
? childTrNode.children[2].textContent.trim()
: undefined;
scheduleItems.push({
startTime: timeOfDay,
endTime: timeOfDay + 1,
dayOfWeek,
subject,
attendees,
location,
});
});
});
});
return scheduleItems;
}
module.exports = parseSchedule;
|