@nbtca/prompt 1.4.2 → 1.5.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.
- package/README.md +27 -58
- package/SECURITY.md +16 -45
- package/dist/app/app.js +167 -64
- package/dist/app/chrome.js +67 -50
- package/dist/app/fields/list-field.js +12 -25
- package/dist/app/fields/text-field.js +3 -8
- package/dist/app/frame.js +16 -23
- package/dist/app/keys.js +110 -2
- package/dist/app/views/docs-render.js +34 -26
- package/dist/app/views/docs.js +280 -68
- package/dist/app/views/events-render.js +21 -27
- package/dist/app/views/events.js +57 -33
- package/dist/app/views/home.js +67 -47
- package/dist/app/views/schedule-grid-cursor.js +9 -18
- package/dist/app/views/schedule-render.js +51 -74
- package/dist/app/views/schedule.js +246 -101
- package/dist/app/views/settings-render.js +8 -19
- package/dist/app/views/settings.js +92 -17
- package/dist/auth/cookie-transport.js +31 -32
- package/dist/auth/errors.js +3 -1
- package/dist/auth/nbt-auth.js +42 -25
- package/dist/auth/session-store.js +17 -9
- package/dist/cli.js +570 -0
- package/dist/config/data.js +9 -11
- package/dist/config/preferences.js +21 -7
- package/dist/core/calendar-day.js +37 -0
- package/dist/core/canvas.js +1 -0
- package/dist/core/capabilities.js +6 -3
- package/dist/core/components/confirm.js +9 -8
- package/dist/core/components/menu.js +64 -38
- package/dist/core/components/messages.js +12 -4
- package/dist/core/components/painter.js +3 -1
- package/dist/core/components/spinner.js +34 -7
- package/dist/core/components/text-input.js +24 -18
- package/dist/core/icons.js +2 -2
- package/dist/core/logo.js +23 -5
- package/dist/core/motion.js +25 -19
- package/dist/core/text.js +186 -69
- package/dist/core/theme.js +0 -28
- package/dist/core/transitions.js +2 -2
- package/dist/core/ui.js +15 -13
- package/dist/core/vim-keys.js +156 -19
- package/dist/features/about.js +23 -0
- package/dist/features/calendar-heatmap.js +16 -40
- package/dist/features/calendar-query.js +1 -2
- package/dist/features/calendar-store.js +27 -0
- package/dist/features/calendar.js +66 -190
- package/dist/features/docs-client.js +225 -0
- package/dist/features/docs.js +615 -298
- package/dist/features/links.js +44 -29
- package/dist/features/schedule-render.js +65 -101
- package/dist/features/schedule-store.js +51 -9
- package/dist/features/schedule-view.js +46 -213
- package/dist/features/status.js +117 -60
- package/dist/features/student-timetable.js +74 -97
- package/dist/features/theme.js +9 -5
- package/dist/features/timetable-sanitize.js +40 -0
- package/dist/features/update.js +12 -29
- package/dist/i18n/index.js +83 -19
- package/dist/i18n/locales/en.json +8 -3
- package/dist/i18n/locales/zh.json +8 -3
- package/dist/index.js +6 -474
- package/dist/logo/ca-dotmatrix.txt +16 -18
- package/dist/main.js +7 -48
- package/package.json +28 -18
- package/bin/nbtca-welcome.js +0 -2
- package/dist/core/components/screen.js +0 -18
- package/dist/core/menu.js +0 -68
- package/dist/features/schedule-query.js +0 -47
- package/dist/features/settings.js +0 -127
- package/dist/logo/ca-logo.png +0 -0
package/package.json
CHANGED
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nbtca/prompt",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"exports": {
|
|
7
7
|
".": "./dist/index.js"
|
|
8
8
|
},
|
|
9
9
|
"bin": {
|
|
10
|
-
"nbtca": "
|
|
11
|
-
"nbtca-welcome": "
|
|
10
|
+
"nbtca": "dist/index.js",
|
|
11
|
+
"nbtca-welcome": "dist/index.js"
|
|
12
12
|
},
|
|
13
13
|
"files": [
|
|
14
14
|
"dist",
|
|
15
|
-
"bin/nbtca-welcome.js",
|
|
16
15
|
"README.md",
|
|
17
16
|
"SECURITY.md",
|
|
18
17
|
"LICENSE"
|
|
@@ -23,10 +22,18 @@
|
|
|
23
22
|
"dev:watch": "tsx watch src/index.ts",
|
|
24
23
|
"build": "tsc",
|
|
25
24
|
"postbuild": "node scripts/copy-assets.js",
|
|
26
|
-
"clean": "
|
|
25
|
+
"clean": "node scripts/clean.js",
|
|
27
26
|
"prebuild": "npm run clean",
|
|
28
|
-
"
|
|
29
|
-
"
|
|
27
|
+
"format": "prettier --write .",
|
|
28
|
+
"format:check": "prettier --check .",
|
|
29
|
+
"lint": "eslint . --max-warnings=0",
|
|
30
|
+
"typecheck": "tsc --project tsconfig.typecheck.json",
|
|
31
|
+
"test": "vitest run && npm run test:cli",
|
|
32
|
+
"test:cli": "npm run build && bash scripts/test-cli.sh",
|
|
33
|
+
"precheck:package": "npm run build",
|
|
34
|
+
"check:package": "node scripts/check-package.mjs",
|
|
35
|
+
"check": "npm run format:check && npm run lint && npm run typecheck && npm test && npm run check:package && npm audit --audit-level=moderate",
|
|
36
|
+
"prepublishOnly": "npm run check"
|
|
30
37
|
},
|
|
31
38
|
"keywords": [
|
|
32
39
|
"cli",
|
|
@@ -39,8 +46,8 @@
|
|
|
39
46
|
"interactive"
|
|
40
47
|
],
|
|
41
48
|
"dependencies": {
|
|
42
|
-
"@nbtca/docs": "^0.
|
|
43
|
-
"@nbtca/nbtcal": "^0.
|
|
49
|
+
"@nbtca/docs": "^0.3.0",
|
|
50
|
+
"@nbtca/nbtcal": "^0.4.0",
|
|
44
51
|
"chalk": "^5.6.2",
|
|
45
52
|
"cheerio": "1.0.0",
|
|
46
53
|
"fetch-cookie": "^3.2.0",
|
|
@@ -51,10 +58,16 @@
|
|
|
51
58
|
"tough-cookie": "^6.0.2"
|
|
52
59
|
},
|
|
53
60
|
"devDependencies": {
|
|
54
|
-
"@
|
|
55
|
-
"@types/node": "
|
|
61
|
+
"@eslint/js": "^9.39.5",
|
|
62
|
+
"@types/node": "20.12.12",
|
|
63
|
+
"eslint": "^9.39.5",
|
|
64
|
+
"eslint-config-prettier": "^10.1.8",
|
|
65
|
+
"globals": "^17.9.0",
|
|
66
|
+
"prettier": "^3.9.6",
|
|
56
67
|
"tsx": "^4.23.5",
|
|
57
68
|
"typescript": "^5.9.3",
|
|
69
|
+
"typescript-eslint": "^8.67.0",
|
|
70
|
+
"vite": "^6.4.3",
|
|
58
71
|
"vitest": "^3.2.7"
|
|
59
72
|
},
|
|
60
73
|
"engines": {
|
|
@@ -67,14 +80,11 @@
|
|
|
67
80
|
},
|
|
68
81
|
"repository": {
|
|
69
82
|
"type": "git",
|
|
70
|
-
"url": "git+https://github.com/nbtca/
|
|
83
|
+
"url": "git+https://github.com/nbtca/Prompt.git"
|
|
71
84
|
},
|
|
72
85
|
"bugs": {
|
|
73
|
-
"url": "https://github.com/nbtca/
|
|
86
|
+
"url": "https://github.com/nbtca/Prompt/issues"
|
|
74
87
|
},
|
|
75
|
-
"homepage": "https://github.com/nbtca/
|
|
76
|
-
"description": "Terminal information system for the NBTCA community"
|
|
77
|
-
"directories": {
|
|
78
|
-
"doc": "docs"
|
|
79
|
-
}
|
|
88
|
+
"homepage": "https://github.com/nbtca/Prompt#readme",
|
|
89
|
+
"description": "Terminal information system for the NBTCA community"
|
|
80
90
|
}
|
package/bin/nbtca-welcome.js
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { glyph, type, space } from '../theme.js';
|
|
2
|
-
export function screenWidth() {
|
|
3
|
-
return Math.min(process.stdout.columns || 80, 64);
|
|
4
|
-
}
|
|
5
|
-
export function renderScreen(opts) {
|
|
6
|
-
const width = opts.width ?? screenWidth();
|
|
7
|
-
const lines = [];
|
|
8
|
-
if (opts.title) {
|
|
9
|
-
lines.push(space.indent + type.heading(opts.title));
|
|
10
|
-
lines.push(space.indent + type.hint(glyph.rule().repeat(width)));
|
|
11
|
-
}
|
|
12
|
-
lines.push(opts.body);
|
|
13
|
-
if (opts.footer) {
|
|
14
|
-
lines.push('');
|
|
15
|
-
lines.push(space.indent + type.hint(opts.footer));
|
|
16
|
-
}
|
|
17
|
-
return lines.join('\n');
|
|
18
|
-
}
|
package/dist/core/menu.js
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import { runMenu } from './components/menu.js';
|
|
2
|
-
import { type, space, glyph } from './theme.js';
|
|
3
|
-
import { clearScreen } from './ui.js';
|
|
4
|
-
import { showCalendar } from '../features/calendar.js';
|
|
5
|
-
import { showDocsMenu } from '../features/docs.js';
|
|
6
|
-
import { showServiceStatus } from '../features/status.js';
|
|
7
|
-
import { showLinksMenu } from '../features/links.js';
|
|
8
|
-
import { showSettingsMenu } from '../features/settings.js';
|
|
9
|
-
import { showStudentTimetableMenu } from '../features/student-timetable.js';
|
|
10
|
-
import { showSchedule } from '../features/schedule-view.js';
|
|
11
|
-
import { t } from '../i18n/index.js';
|
|
12
|
-
function getMainMenuOptions() {
|
|
13
|
-
const trans = t();
|
|
14
|
-
return [
|
|
15
|
-
{ value: 'events', label: trans.menu.events, hint: trans.menu.eventsDesc || undefined },
|
|
16
|
-
{ value: 'schedule', label: t().timetable.menuEntry },
|
|
17
|
-
{ value: 'timetable', label: trans.menu.timetable, hint: trans.menu.timetableDesc || undefined },
|
|
18
|
-
{ value: 'docs', label: trans.menu.docs, hint: trans.menu.docsDesc || undefined },
|
|
19
|
-
{ value: 'status', label: trans.menu.status, hint: trans.menu.statusDesc || undefined },
|
|
20
|
-
{ value: 'links', label: trans.menu.links, hint: trans.menu.linksDesc || undefined },
|
|
21
|
-
{ value: 'settings', label: trans.menu.settings, hint: trans.menu.settingsDesc || undefined },
|
|
22
|
-
];
|
|
23
|
-
}
|
|
24
|
-
export async function showMainMenu() {
|
|
25
|
-
let first = true;
|
|
26
|
-
while (true) {
|
|
27
|
-
if (!first)
|
|
28
|
-
clearScreen();
|
|
29
|
-
first = false;
|
|
30
|
-
const trans = t();
|
|
31
|
-
const footer = `${glyph.updown()} ${trans.menu.hintMove} ${glyph.enter()} ${trans.menu.hintOpen} q ${trans.menu.hintQuit}`;
|
|
32
|
-
const action = await runMenu({
|
|
33
|
-
title: trans.menu.chooseAction,
|
|
34
|
-
options: getMainMenuOptions(),
|
|
35
|
-
footer,
|
|
36
|
-
});
|
|
37
|
-
if (action === null) {
|
|
38
|
-
console.log(space.indent + type.hint(t().common.goodbye));
|
|
39
|
-
process.exit(0);
|
|
40
|
-
}
|
|
41
|
-
await runMenuAction(action);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
export async function runMenuAction(action) {
|
|
45
|
-
switch (action) {
|
|
46
|
-
case 'events':
|
|
47
|
-
await showCalendar();
|
|
48
|
-
break;
|
|
49
|
-
case 'schedule':
|
|
50
|
-
await showSchedule();
|
|
51
|
-
break;
|
|
52
|
-
case 'timetable':
|
|
53
|
-
await showStudentTimetableMenu();
|
|
54
|
-
break;
|
|
55
|
-
case 'docs':
|
|
56
|
-
await showDocsMenu();
|
|
57
|
-
break;
|
|
58
|
-
case 'status':
|
|
59
|
-
await showServiceStatus();
|
|
60
|
-
break;
|
|
61
|
-
case 'links':
|
|
62
|
-
await showLinksMenu();
|
|
63
|
-
break;
|
|
64
|
-
case 'settings':
|
|
65
|
-
await showSettingsMenu();
|
|
66
|
-
break;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
const DAY_MS = 86400000;
|
|
2
|
-
export function currentWeekNumber(weekOneMonday, now) {
|
|
3
|
-
const base = new Date(`${weekOneMonday}T00:00:00`);
|
|
4
|
-
const days = Math.floor((now.getTime() - base.getTime()) / DAY_MS);
|
|
5
|
-
return Math.floor(days / 7) + 1;
|
|
6
|
-
}
|
|
7
|
-
export function campusWeekday(now) {
|
|
8
|
-
return ((now.getDay() + 6) % 7) + 1;
|
|
9
|
-
}
|
|
10
|
-
export function meetingsInWeek(meetings, week) {
|
|
11
|
-
return meetings.filter((mtg) => mtg.weeks.includes(week));
|
|
12
|
-
}
|
|
13
|
-
export function meetingsOnDay(meetings, weekday, week) {
|
|
14
|
-
return meetings
|
|
15
|
-
.filter((mtg) => mtg.weekday === weekday && mtg.weeks.includes(week))
|
|
16
|
-
.sort((a, b) => a.startPeriod - b.startPeriod);
|
|
17
|
-
}
|
|
18
|
-
export function periodStartDate(weekOneMonday, week, weekday, period, periods) {
|
|
19
|
-
const p = periods.find((x) => x.period === period);
|
|
20
|
-
if (!p)
|
|
21
|
-
return null;
|
|
22
|
-
const base = new Date(`${weekOneMonday}T00:00:00`);
|
|
23
|
-
const date = new Date(base.getTime() + ((week - 1) * 7 + (weekday - 1)) * DAY_MS);
|
|
24
|
-
const parts = p.start.split(':');
|
|
25
|
-
date.setHours(Number.parseInt(parts[0] ?? '0', 10), Number.parseInt(parts[1] ?? '0', 10), 0, 0);
|
|
26
|
-
return date;
|
|
27
|
-
}
|
|
28
|
-
export function nextMeeting(meetings, periods, weekOneMonday, now) {
|
|
29
|
-
let best = null;
|
|
30
|
-
for (const meeting of meetings) {
|
|
31
|
-
for (const week of meeting.weeks) {
|
|
32
|
-
const start = periodStartDate(weekOneMonday, week, meeting.weekday, meeting.startPeriod, periods);
|
|
33
|
-
if (start && start.getTime() > now.getTime() && (!best || start.getTime() < best.start.getTime())) {
|
|
34
|
-
best = { meeting, start };
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
return best;
|
|
39
|
-
}
|
|
40
|
-
/** The meeting occupying a grid cell, whether it starts there or is a later
|
|
41
|
-
* period of a meeting that started earlier the same day -- one condition
|
|
42
|
-
* (`startPeriod <= period <= endPeriod`) covers both cases, matching
|
|
43
|
-
* renderWeekGrid's own starting/continuing lookup so "does this cell have a
|
|
44
|
-
* meeting" and "what does the grid actually draw there" never disagree. */
|
|
45
|
-
export function meetingAtCursor(meetings, week, cursor) {
|
|
46
|
-
return meetingsInWeek(meetings, week).find((m) => m.weekday === cursor.weekday && m.startPeriod <= cursor.period && cursor.period <= m.endPeriod) ?? null;
|
|
47
|
-
}
|
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
import chalk from 'chalk';
|
|
2
|
-
import { applyColorModePreference, loadPreferences, resetPreferences, setColorMode, setIconMode, } from '../config/preferences.js';
|
|
3
|
-
import { pickIcon } from '../core/icons.js';
|
|
4
|
-
import { resetIconCache } from '../core/icons.js';
|
|
5
|
-
import { padEndV } from '../core/text.js';
|
|
6
|
-
import { success, warning } from '../core/ui.js';
|
|
7
|
-
import { APP_INFO, URLS } from '../config/data.js';
|
|
8
|
-
import { t, getCurrentLanguage, saveLanguagePreference, clearTranslationCache } from '../i18n/index.js';
|
|
9
|
-
import { runMenu, menuFooter } from '../core/components/menu.js';
|
|
10
|
-
import { note } from '../core/components/note.js';
|
|
11
|
-
import { enterScreen, breadcrumb } from '../core/transitions.js';
|
|
12
|
-
function notifyResult(saved, successMsg, warningMsg) {
|
|
13
|
-
if (saved) {
|
|
14
|
-
success(successMsg);
|
|
15
|
-
}
|
|
16
|
-
else {
|
|
17
|
-
warning(warningMsg);
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
function showAbout() {
|
|
21
|
-
const trans = t();
|
|
22
|
-
const pad = 12;
|
|
23
|
-
const row = (label, value) => `${chalk.dim(padEndV(label, pad))}${value}`;
|
|
24
|
-
const link = (label, url) => row(label, chalk.cyan(url));
|
|
25
|
-
const content = [
|
|
26
|
-
row(trans.about.project, APP_INFO.name),
|
|
27
|
-
row(trans.about.version, `v${APP_INFO.version}`),
|
|
28
|
-
row(trans.about.description, trans.about.descriptionText),
|
|
29
|
-
'',
|
|
30
|
-
link(trans.about.github, APP_INFO.repository),
|
|
31
|
-
link(trans.about.website, URLS.homepage),
|
|
32
|
-
link(trans.about.email, URLS.email),
|
|
33
|
-
'',
|
|
34
|
-
row(trans.about.license, `MIT ${pickIcon('·', '|')} ${trans.about.author}: m1ngsama`),
|
|
35
|
-
].join('\n');
|
|
36
|
-
note(content, trans.about.title);
|
|
37
|
-
}
|
|
38
|
-
export async function showSettingsMenu() {
|
|
39
|
-
await enterScreen(breadcrumb(t().menu.settings));
|
|
40
|
-
while (true) {
|
|
41
|
-
const trans = t();
|
|
42
|
-
const prefs = loadPreferences();
|
|
43
|
-
const currentLang = getCurrentLanguage();
|
|
44
|
-
const footer = menuFooter();
|
|
45
|
-
const action = await runMenu({
|
|
46
|
-
title: trans.theme.chooseAction,
|
|
47
|
-
options: [
|
|
48
|
-
{ value: 'language', label: trans.language.selectLanguage, hint: currentLang === 'zh' ? trans.language.zh : trans.language.en },
|
|
49
|
-
{ value: 'icon', label: trans.theme.iconMode, hint: prefs.iconMode },
|
|
50
|
-
{ value: 'color', label: trans.theme.colorMode, hint: prefs.colorMode },
|
|
51
|
-
{ value: 'reset', label: trans.theme.resetLabel },
|
|
52
|
-
{ value: 'about', label: trans.about.title },
|
|
53
|
-
],
|
|
54
|
-
footer,
|
|
55
|
-
});
|
|
56
|
-
if (action === null)
|
|
57
|
-
return;
|
|
58
|
-
if (action === 'about') {
|
|
59
|
-
showAbout();
|
|
60
|
-
continue;
|
|
61
|
-
}
|
|
62
|
-
if (action === 'language') {
|
|
63
|
-
const langOptions = [
|
|
64
|
-
{ value: 'zh', label: trans.language.zh, hint: currentLang === 'zh' ? trans.common.current : undefined },
|
|
65
|
-
{ value: 'en', label: trans.language.en, hint: currentLang === 'en' ? trans.common.current : undefined },
|
|
66
|
-
];
|
|
67
|
-
const language = await runMenu({
|
|
68
|
-
title: trans.language.selectLanguage,
|
|
69
|
-
options: langOptions,
|
|
70
|
-
footer,
|
|
71
|
-
initialIndex: Math.max(0, langOptions.findIndex(o => o.value === currentLang)),
|
|
72
|
-
});
|
|
73
|
-
if (language === null)
|
|
74
|
-
continue;
|
|
75
|
-
if (language !== currentLang) {
|
|
76
|
-
const saved = saveLanguagePreference(language);
|
|
77
|
-
clearTranslationCache();
|
|
78
|
-
notifyResult(saved, t().language.changed, t().language.changedSessionOnly);
|
|
79
|
-
}
|
|
80
|
-
continue;
|
|
81
|
-
}
|
|
82
|
-
if (action === 'icon') {
|
|
83
|
-
const iconOptions = [
|
|
84
|
-
{ value: 'auto', label: trans.theme.modeAuto, hint: prefs.iconMode === 'auto' ? trans.common.current : undefined },
|
|
85
|
-
{ value: 'ascii', label: trans.theme.modeAscii, hint: prefs.iconMode === 'ascii' ? trans.common.current : undefined },
|
|
86
|
-
{ value: 'unicode', label: trans.theme.modeUnicode, hint: prefs.iconMode === 'unicode' ? trans.common.current : undefined },
|
|
87
|
-
];
|
|
88
|
-
const mode = await runMenu({
|
|
89
|
-
title: trans.theme.chooseIconMode,
|
|
90
|
-
options: iconOptions,
|
|
91
|
-
footer,
|
|
92
|
-
initialIndex: Math.max(0, iconOptions.findIndex(o => o.value === prefs.iconMode)),
|
|
93
|
-
});
|
|
94
|
-
if (mode === null)
|
|
95
|
-
continue;
|
|
96
|
-
const saved = setIconMode(mode);
|
|
97
|
-
resetIconCache();
|
|
98
|
-
notifyResult(saved, trans.theme.updated, trans.theme.updatedSessionOnly);
|
|
99
|
-
continue;
|
|
100
|
-
}
|
|
101
|
-
if (action === 'color') {
|
|
102
|
-
const colorOptions = [
|
|
103
|
-
{ value: 'auto', label: trans.theme.modeAuto, hint: prefs.colorMode === 'auto' ? trans.common.current : undefined },
|
|
104
|
-
{ value: 'on', label: trans.theme.modeOn, hint: prefs.colorMode === 'on' ? trans.common.current : undefined },
|
|
105
|
-
{ value: 'off', label: trans.theme.modeOff, hint: prefs.colorMode === 'off' ? trans.common.current : undefined },
|
|
106
|
-
];
|
|
107
|
-
const mode = await runMenu({
|
|
108
|
-
title: trans.theme.chooseColorMode,
|
|
109
|
-
options: colorOptions,
|
|
110
|
-
footer,
|
|
111
|
-
initialIndex: Math.max(0, colorOptions.findIndex(o => o.value === prefs.colorMode)),
|
|
112
|
-
});
|
|
113
|
-
if (mode === null)
|
|
114
|
-
continue;
|
|
115
|
-
const saved = setColorMode(mode);
|
|
116
|
-
applyColorModePreference(false);
|
|
117
|
-
notifyResult(saved, trans.theme.updated, trans.theme.updatedSessionOnly);
|
|
118
|
-
continue;
|
|
119
|
-
}
|
|
120
|
-
if (action === 'reset') {
|
|
121
|
-
const saved = resetPreferences();
|
|
122
|
-
resetIconCache();
|
|
123
|
-
applyColorModePreference(false);
|
|
124
|
-
notifyResult(saved, trans.theme.reset, trans.theme.resetSessionOnly);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
}
|
package/dist/logo/ca-logo.png
DELETED
|
Binary file
|