@ranzenjs/client 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -70,9 +70,22 @@ export function parseCourse(document, id, drift = ignoreDrift) {
70
70
  marks: parseMarks(document, drift),
71
71
  exams: parseExams(document, drift),
72
72
  attendance: hours(rows(one('#attendanceTable', document)), drift),
73
- hasFirstSemester: all('a[href*="halb=1"]', document).some((link) => queryParam(attr(link, 'href'), 'id') === id)
73
+ firstSemester: firstSemester(document, id)
74
74
  };
75
75
  }
76
+ // Prefer a link to the course's own id, else the first-semester button, which is hidden in print.
77
+ function firstSemester(document, id) {
78
+ const links = all('a[href]', document).filter((link) => {
79
+ const href = attr(link, 'href') ?? '';
80
+ return (/(^|\/)meinunterricht\.php\?/.test(href) &&
81
+ queryParam(href, 'a') === 'sus_view' &&
82
+ queryParam(href, 'halb') === '1');
83
+ });
84
+ if (links.some((link) => queryParam(attr(link, 'href'), 'id') === id))
85
+ return id;
86
+ const button = links.find((link) => ['btn', 'btn-default', 'hidden-print'].every((name) => hasClass(link, name)));
87
+ return queryParam(attr(button, 'href'), 'id');
88
+ }
76
89
  // Entries carry their id in data-entry; rows without one are reported, never guessed.
77
90
  function entryRows(table, what, drift) {
78
91
  return table.filter((row) => {
@@ -165,7 +178,7 @@ function submission(group, drift) {
165
178
  }
166
179
  ];
167
180
  }
168
- // Each mark is a row of name, date and value, optionally followed by a one-cell comment row.
181
+ // Each mark is a row of name, date and value, optionally followed by a comment in its own row.
169
182
  function parseMarks(document, drift) {
170
183
  const marks = [];
171
184
  for (const row of rows(one('#marks', document))) {
@@ -174,8 +187,11 @@ function parseMarks(document, drift) {
174
187
  if (name && date && value && !rest.length) {
175
188
  marks.push({ name: text(name), date: text(date), value: text(value), comment: null });
176
189
  }
177
- else if (name && !date && last) {
178
- last.comment = text(name).replace(/^[^:]*:\s*/, '') || null;
190
+ else if (last &&
191
+ name &&
192
+ !value &&
193
+ (!date || (!text(name) && attr(date, 'colspan') === '2'))) {
194
+ last.comment = text(date ?? name).replace(/^[^:]*:\s*/, '') || last.comment;
179
195
  }
180
196
  else
181
197
  drift('A mark row has an unknown shape.');
@@ -263,8 +279,12 @@ function hours(table, drift) {
263
279
  function teacher(element) {
264
280
  const title = (attr(element, 'title') ?? '').replace(/\s*\(([^)]*)\)\s*$/, '');
265
281
  const code = text(element) || /\(([^)]*)\)\s*$/.exec(attr(element, 'title') ?? '')?.[1] || null;
266
- const [lastName, firstName] = title.split(',').map((part) => part.trim());
267
- return { code, firstName: firstName || null, lastName: lastName || null };
282
+ const [lastName = '', ...firstNames] = title.split(',');
283
+ return {
284
+ code,
285
+ firstName: firstNames.join(',').trim() || null,
286
+ lastName: lastName.trim() || null
287
+ };
268
288
  }
269
289
  function file(element) {
270
290
  const size = text(one('small', element)).replace(/^\(|\)$/g, '');
@@ -277,7 +297,7 @@ function file(element) {
277
297
  function periods(label, drift) {
278
298
  if (!label)
279
299
  return null;
280
- const match = /(\d+)\.(?:\s*-\s*(\d+)\.)?\s*Stunde/.exec(label);
300
+ const match = /^(\d+)\.?(?:\s*[-–]\s*(\d+)\.?)?(?:\s*Stunden?)?$/.exec(label.trim());
281
301
  if (!match) {
282
302
  drift('A history row has unreadable periods.');
283
303
  return null;
@@ -92,8 +92,8 @@ export interface Course extends CourseRef {
92
92
  marks: Mark[];
93
93
  exams: Exam[];
94
94
  attendance: Record<string, number>;
95
- /** Whether the portal links this course's first semester. */
96
- hasFirstSemester: boolean;
95
+ /** Id the portal links for this course's first semester; read it with `course(id, { semester: 1 })`. */
96
+ firstSemester: string | null;
97
97
  }
98
98
  export interface EntryRef {
99
99
  course: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ranzenjs/client",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
4
4
  "description": "Typed client for Schulportal Hessen (SPH, LANIS)",
5
5
  "license": "MIT",
6
6
  "author": "Suko",