ci: use Gitea API for releases #2
+50
@@ -0,0 +1,50 @@
|
|||||||
|
(function (root, factory) {
|
||||||
|
if (typeof module === 'object' && module.exports) {
|
||||||
|
module.exports = factory();
|
||||||
|
} else {
|
||||||
|
root.ISMIStools = Object.assign(root.ISMIStools || {}, factory());
|
||||||
|
}
|
||||||
|
})(typeof self !== 'undefined' ? self : this, function () {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
function cleanText(s) {
|
||||||
|
return String(s == null ? '' : s)
|
||||||
|
.replace(/<[^>]+>/g, ' ')
|
||||||
|
.replace(/ /gi, ' ')
|
||||||
|
.replace(/\s+/g, ' ')
|
||||||
|
.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
function extractRows(html) {
|
||||||
|
const rows = [];
|
||||||
|
const trRe = /<tr[^>]*>([\s\S]*?)<\/tr>/gi;
|
||||||
|
let trMatch;
|
||||||
|
while ((trMatch = trRe.exec(html)) !== null) {
|
||||||
|
const rowHtml = trMatch[1];
|
||||||
|
if (/<th/i.test(rowHtml)) continue;
|
||||||
|
const tds = [];
|
||||||
|
const tdRe = /<td[^>]*>([\s\S]*?)<\/td>/gi;
|
||||||
|
let tdMatch;
|
||||||
|
while ((tdMatch = tdRe.exec(rowHtml)) !== null) {
|
||||||
|
tds.push(cleanText(tdMatch[1]));
|
||||||
|
}
|
||||||
|
rows.push(tds);
|
||||||
|
}
|
||||||
|
return rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseStudyLoadTable(html) {
|
||||||
|
return extractRows(html)
|
||||||
|
.filter((tds) => tds.length >= 6)
|
||||||
|
.map((tds) => ({
|
||||||
|
group: tds[0],
|
||||||
|
courseCode: tds[1],
|
||||||
|
schedule: tds[2],
|
||||||
|
faculty: tds[3],
|
||||||
|
units: tds[4],
|
||||||
|
status: tds[5]
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
return { parseStudyLoadTable };
|
||||||
|
});
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
const { test } = require('node:test');
|
||||||
|
const assert = require('node:assert');
|
||||||
|
const fs = require('node:fs');
|
||||||
|
const path = require('node:path');
|
||||||
|
const { parseStudyLoadTable } = require('../parsers.js');
|
||||||
|
|
||||||
|
const fixture = fs.readFileSync(path.join(__dirname, 'fixtures', 'study-load-table.html'), 'utf8');
|
||||||
|
|
||||||
|
test('parseStudyLoadTable extracts all course rows', () => {
|
||||||
|
const rows = parseStudyLoadTable(fixture);
|
||||||
|
assert.strictEqual(rows.length, 5);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('parseStudyLoadTable maps columns correctly', () => {
|
||||||
|
const rows = parseStudyLoadTable(fixture);
|
||||||
|
const first = rows[0];
|
||||||
|
assert.strictEqual(first.group, '1');
|
||||||
|
assert.strictEqual(first.courseCode, 'CS 5105');
|
||||||
|
assert.strictEqual(first.units, '3.00');
|
||||||
|
assert.strictEqual(first.status, 'DISSOLVED');
|
||||||
|
assert.ok(first.schedule.includes('F 01:30 PM'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('parseStudyLoadTable handles empty faculty', () => {
|
||||||
|
const rows = parseStudyLoadTable(fixture);
|
||||||
|
const it4102 = rows.find(r => r.courseCode === 'IT 4102N');
|
||||||
|
assert.strictEqual(it4102.faculty, '');
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user