chuvsu-js 4.0.0 → 4.0.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.
@@ -162,6 +162,7 @@ function parseSessionEntry(td) {
162
162
  const plainText = text(td);
163
163
  if (!plainText)
164
164
  return null;
165
+ const possibleChanges = (td.getAttribute("class") ?? "").includes("want") || undefined;
165
166
  const subjectEl = td.querySelector('span[style*="color: blue"]');
166
167
  const subject = subjectEl ? text(subjectEl) : "";
167
168
  if (!subject)
@@ -172,6 +173,14 @@ function parseSessionEntry(td) {
172
173
  // Type: parenthesized text after </span>, case-insensitive
173
174
  const typeMatch = plainText.match(FLEXIBLE_LESSON_TYPE_RE_I);
174
175
  const type = typeMatch ? typeMatch[1].replace(/\.$/, "").toLowerCase() : "";
176
+ const subgroupMatch = plainText.match(SUBGROUP_RE);
177
+ const parts = fullHtml
178
+ .split(/<br\s*\/?>/i)
179
+ .map((part) => part.replace(/<[^>]*>/g, "").trim())
180
+ .filter((part) => part.length > 0);
181
+ const teacherPart = parts.find((part) => !part.includes(subject) &&
182
+ !/^\d{2}:\d{2}\s*-\s*\d{2}:\d{2}$/.test(part) &&
183
+ !SUBGROUP_RE.test(part)) ?? "";
175
184
  // Time: after <br>, format HH:MM - HH:MM
176
185
  const timeMatch = fullHtml.match(/<br\s*\/?>\s*(\d{2}:\d{2})\s*-\s*(\d{2}:\d{2})/);
177
186
  if (!timeMatch)
@@ -182,8 +191,10 @@ function parseSessionEntry(td) {
182
191
  subject,
183
192
  type,
184
193
  weeks: { from: 0, to: 0 },
185
- teacher: { name: "" },
194
+ teacher: parseTeacher(teacherPart),
186
195
  groups: [],
196
+ subgroup: subgroupMatch ? parseInt(subgroupMatch[1]) : undefined,
197
+ possibleChanges,
187
198
  },
188
199
  timeStart: parseTime(timeMatch[1]),
189
200
  timeEnd: parseTime(timeMatch[2]),
@@ -1,6 +1,7 @@
1
1
  import { parseTeacher, text } from "../../common/parse.js";
2
2
  import { parseGroupsString } from "./groups.js";
3
3
  import { LESSON_TYPE_PATTERN, LESSON_TYPE_RE, LESSON_TYPE_RE_I, SUBGROUP_RE, } from "./patterns.js";
4
+ const GROUP_CODE_RE = /[A-ZА-ЯЁ]{1,}(?:-[A-ZА-ЯЁa-zа-яё0-9]+)+/u;
4
5
  export function parseDate(dd, mm, yyyy) {
5
6
  return new Date(parseInt(yyyy), parseInt(mm) - 1, parseInt(dd));
6
7
  }
@@ -29,8 +30,7 @@ export function parseTransferDiv(div) {
29
30
  const cleaned = part.trim();
30
31
  if (!cleaned)
31
32
  continue;
32
- const groups = parseGroupsString(cleaned);
33
- if (groups.length > 0) {
33
+ if (GROUP_CODE_RE.test(cleaned)) {
34
34
  groupsPart = cleaned;
35
35
  continue;
36
36
  }
@@ -1,5 +1,5 @@
1
- export declare const LESSON_TYPE_PATTERN = "\u043B\u043A|\u043F\u0440|\u043B\u0431|\u0437\u0430\u0447|\u044D\u043A\u0437|\u043A\u043E\u043D\u0441";
2
- export declare const FLEXIBLE_LESSON_TYPE_PATTERN = "\u043B\u043A|\u043F\u0440|\u043B\u0431|\u0437\u0430\u0447|\u044D\u043A\u0437|\u043A\u043E\u043D\u0441\\.?|\u042D\u043A\u0437";
1
+ export declare const LESSON_TYPE_PATTERN = "\u043B\u043A|\u043F\u0440|\u043B\u0431|\u0437\u0430\u0447\u043E|\u0437\u0430\u0447|\u044D\u043A\u0437|\u043A\u043E\u043D\u0441|\u043A\u043F";
2
+ export declare const FLEXIBLE_LESSON_TYPE_PATTERN = "(?:\u043B\u043A|\u043F\u0440|\u043B\u0431|\u0437\u0430\u0447\u043E|\u0437\u0430\u0447|\u044D\u043A\u0437|\u043A\u043E\u043D\u0441|\u043A\u043F)\\.?|\u042D\u043A\u0437";
3
3
  export declare const LESSON_TYPE_RE: RegExp;
4
4
  export declare const LESSON_TYPE_RE_I: RegExp;
5
5
  export declare const FLEXIBLE_LESSON_TYPE_RE_I: RegExp;
@@ -1,5 +1,5 @@
1
- export const LESSON_TYPE_PATTERN = "лк|пр|лб|зач|экз|конс";
2
- export const FLEXIBLE_LESSON_TYPE_PATTERN = `${LESSON_TYPE_PATTERN}\\.?|Экз`;
1
+ export const LESSON_TYPE_PATTERN = "лк|пр|лб|зачо|зач|экз|конс|кп";
2
+ export const FLEXIBLE_LESSON_TYPE_PATTERN = `(?:${LESSON_TYPE_PATTERN})\\.?|Экз`;
3
3
  export const LESSON_TYPE_RE = new RegExp(`\\((${LESSON_TYPE_PATTERN})\\)`);
4
4
  export const LESSON_TYPE_RE_I = new RegExp(`\\((${LESSON_TYPE_PATTERN})\\)`, "i");
5
5
  export const FLEXIBLE_LESSON_TYPE_RE_I = new RegExp(`\\((${FLEXIBLE_LESSON_TYPE_PATTERN})\\)`, "i");
@@ -116,6 +116,7 @@ function parseTeacherSessionEntry(td) {
116
116
  const plainText = text(td);
117
117
  if (!plainText)
118
118
  return null;
119
+ const possibleChanges = (td.getAttribute("class") ?? "").includes("want") || undefined;
119
120
  const subjectEl = td.querySelector('span[style*="color: blue"]');
120
121
  const subject = subjectEl ? text(subjectEl) : "";
121
122
  if (!subject)
@@ -124,6 +125,7 @@ function parseTeacherSessionEntry(td) {
124
125
  const room = roomMatch ? roomMatch[1].trim() : "";
125
126
  const typeMatch = plainText.match(FLEXIBLE_LESSON_TYPE_RE_I);
126
127
  const type = typeMatch ? typeMatch[1].replace(/\.$/, "").toLowerCase() : "";
128
+ const subgroupMatch = plainText.match(SUBGROUP_RE);
127
129
  // Groups: text between </span> type and <br>time
128
130
  const groupsMatch = fullHtml.match(new RegExp(`\\((?:${FLEXIBLE_LESSON_TYPE_PATTERN})\\)\\s*([^<]+?)\\s*<br`, "i"));
129
131
  const timeMatch = fullHtml.match(/<br\s*\/?>\s*(\d{2}:\d{2})\s*-\s*(\d{2}:\d{2})/);
@@ -137,6 +139,8 @@ function parseTeacherSessionEntry(td) {
137
139
  weeks: { from: 0, to: 0 },
138
140
  teacher: { name: "" },
139
141
  groups: parseGroupsString(groupsMatch?.[1]),
142
+ subgroup: subgroupMatch ? parseInt(subgroupMatch[1]) : undefined,
143
+ possibleChanges,
140
144
  },
141
145
  timeStart: parseTime(timeMatch[1]),
142
146
  timeEnd: parseTime(timeMatch[2]),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chuvsu-js",
3
- "version": "4.0.0",
3
+ "version": "4.0.1",
4
4
  "description": "Node.js library for ChuvSU student portal (lk.chuvsu.ru) and schedule (tt.chuvsu.ru)",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",