This commit is contained in:
7
.gitignore
vendored
7
.gitignore
vendored
@@ -3,3 +3,10 @@ volume/browser
|
|||||||
db
|
db
|
||||||
downloads
|
downloads
|
||||||
errors
|
errors
|
||||||
|
|
||||||
|
# Web
|
||||||
|
web/public
|
||||||
|
web/resources/_gen/
|
||||||
|
web/assets/jsconfig.json
|
||||||
|
web/hugo_stats.json
|
||||||
|
web/.hugo_build.lock
|
||||||
|
|||||||
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
[submodule "web/themes/PaperMod"]
|
||||||
|
path = web/themes/PaperMod
|
||||||
|
url = https://github.com/adityatelange/hugo-PaperMod.git
|
||||||
@@ -10,6 +10,9 @@ COPY package*.json ./
|
|||||||
# Install dependencies
|
# Install dependencies
|
||||||
RUN npm install
|
RUN npm install
|
||||||
|
|
||||||
|
# Build
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
# Copy app source code
|
# Copy app source code
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,9 @@
|
|||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "server.js",
|
"main": "server.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "concurrently \"node server.js\" \"node cron-runner.js\""
|
"start": "concurrently \"node server.js\" \"node cron-runner.js\"",
|
||||||
|
"build": "cd web && hugo --gc --minify",
|
||||||
|
"dev-web": "cd web && hugo serve"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"body-parser": "^2.2.0",
|
"body-parser": "^2.2.0",
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
// Rules: start and end in 24h format, interval in minutes
|
// Rules: start and end in 24h format, interval in minutes
|
||||||
|
|
||||||
export const scheduleRules = [
|
export const scheduleRules = [
|
||||||
{ start: "0:00", end: "3:00", interval: 180 },
|
{ start: "0:00", end: "3:00", interval: 180 },
|
||||||
{ start: "3:00", end: "4:00", interval: 60 },
|
{ start: "3:00", end: "4:00", interval: 60 },
|
||||||
|
|||||||
26
server.js
26
server.js
@@ -11,13 +11,20 @@ globalThis.File = class File {};
|
|||||||
|
|
||||||
app.use(bodyParser.json());
|
app.use(bodyParser.json());
|
||||||
|
|
||||||
app.get('/', async (_, res) => {
|
app.get('/', async (req, res) => {
|
||||||
const dataStr = await fs.readFile(path.join(process.cwd(), "db", "current.json"), "utf8");
|
const userAgent = req.headers['user-agent'] || '';
|
||||||
const data = JSON.parse(dataStr);
|
const isBrowser = /Mozilla|Chrome|Firefox|Safari|Edg/.test(userAgent);
|
||||||
|
|
||||||
data["status"]["currentUpdateSchedule"] = getCurrentInterval();
|
if (isBrowser) {
|
||||||
|
res.sendFile(path.join(process.cwd(), "web", "public", "index.html"));
|
||||||
|
} else {
|
||||||
|
const dataStr = await fs.readFile(path.join(process.cwd(), "db", "current.json"), "utf8");
|
||||||
|
const data = JSON.parse(dataStr);
|
||||||
|
|
||||||
res.json(data);
|
data["status"]["currentUpdateSchedule"] = getCurrentInterval();
|
||||||
|
|
||||||
|
res.json(data);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
app.get('/versioned/v1', async (_, res) => {
|
app.get('/versioned/v1', async (_, res) => {
|
||||||
@@ -49,13 +56,9 @@ app.post("/report", async (req, res) => {
|
|||||||
return res.status(400).json({ error: "Invalid location value." });
|
return res.status(400).json({ error: "Invalid location value." });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const url = `https://n8n.local.jzitnik.dev/webhook/${process.env.WEBHOOK_UUID}`;
|
const url = `https://n8n.local.jzitnik.dev/webhook/${process.env.WEBHOOK_UUID}`;
|
||||||
|
|
||||||
console.log(url)
|
|
||||||
|
|
||||||
let resp;
|
let resp;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
resp = await fetch(url, {
|
resp = await fetch(url, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
@@ -77,6 +80,11 @@ app.post("/report", async (req, res) => {
|
|||||||
res.status(200).json({ message: "Report received successfully." });
|
res.status(200).json({ message: "Report received successfully." });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
app.use(express.static(path.join(process.cwd(), 'web/public'), {
|
||||||
|
index: 'index.html',
|
||||||
|
extensions: ['html'],
|
||||||
|
}));
|
||||||
|
|
||||||
app.listen(PORT, () => {
|
app.listen(PORT, () => {
|
||||||
console.log(`Server is running at http://localhost:${PORT}`);
|
console.log(`Server is running at http://localhost:${PORT}`);
|
||||||
});
|
});
|
||||||
|
|||||||
103
web/content/posts/api-usage/index.md
Normal file
103
web/content/posts/api-usage/index.md
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
---
|
||||||
|
title: "API Dokumentace Ječná Rozvrh"
|
||||||
|
date: 2025-12-20
|
||||||
|
tags: ["api", "docs"]
|
||||||
|
---
|
||||||
|
|
||||||
|
Vítejte v dokumentaci pro API systému Ječná Rozvrh. Toto API poskytuje programový přístup k rozvrhům, suplování a dalším informacím.
|
||||||
|
|
||||||
|
## Základní Informace
|
||||||
|
|
||||||
|
### URL
|
||||||
|
Všechny cesty v této dokumentaci jsou relativní k následující základní URL:
|
||||||
|
`https://jecnarozvrh.jzitnik.dev/`
|
||||||
|
|
||||||
|
### Zastaralý Endpoint: `GET /`
|
||||||
|
|
||||||
|
Kořenový endpoint (`/`) je **zastaralý (deprecated)**.
|
||||||
|
|
||||||
|
Ačkoliv v současnosti vrací stejná data jako `/versioned/v1`, jeho podpora může být v budoucnu ukončena. **Prosím, nepoužívejte tento endpoint pro nové projekty a existující projekty aktualizujte na verziovaný endpoint.**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Dostupné Verze API
|
||||||
|
|
||||||
|
API je verziované, aby byla zajištěna zpětná kompatibilita. Zde je seznam dostupných verzí:
|
||||||
|
|
||||||
|
- ### [Verze 1 (v1)](v1)
|
||||||
|
**Status:** Stabilní
|
||||||
|
**Endpoint:** `/versioned/v1`
|
||||||
|
|
||||||
|
Toto je aktuální a doporučená verze API. Klikněte na odkaz pro zobrazení kompletní dokumentace pro v1.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Nezařazené Endpointy
|
||||||
|
|
||||||
|
Některé jednodušší endpointy nejsou verziované.
|
||||||
|
|
||||||
|
### Stavový Endpoint: `GET /status`
|
||||||
|
|
||||||
|
Tento endpoint slouží k rychlé kontrole stavu scraperu, který je zodpovědný za stahování a zpracování dat.
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Zobrazit možné odpovědi</summary>
|
||||||
|
|
||||||
|
- **Scraper je v pořádku:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"working": true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- **Scraper narazil na problém:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"working": false,
|
||||||
|
"message": "Zde bude podrobnější popis chyby, např. 'Failed to log in'."
|
||||||
|
}
|
||||||
|
```
|
||||||
|
</details>
|
||||||
|
|
||||||
|
### Report Endpoint: `POST /report`
|
||||||
|
|
||||||
|
Tento endpoint slouží k nahlášení chyby nebo nesrovnalosti v datech.
|
||||||
|
|
||||||
|
**Tělo požadavku (Request Body):**
|
||||||
|
|
||||||
|
Požadavek musí obsahovat JSON objekt s následujícími poli:
|
||||||
|
|
||||||
|
- `class` (string, povinné): Název třídy, které se hlášení týká.
|
||||||
|
- `location` (string, povinné): Místo, kde se chyba vyskytla. Povolené hodnoty jsou:
|
||||||
|
- `"TIMETABLE"`
|
||||||
|
- `"ABSENCES"`
|
||||||
|
- `"OTHER"`
|
||||||
|
- `content` (string, povinné): Popis problému.
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Zobrazit příklad těla požadavku</summary>
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"class": "C4a",
|
||||||
|
"location": "TIMETABLE",
|
||||||
|
"content": "V páté hodině chybí předmět, ale má tam být suplování."
|
||||||
|
}
|
||||||
|
```
|
||||||
|
</details>
|
||||||
|
|
||||||
|
**Odpovědi (Responses):**
|
||||||
|
|
||||||
|
- **`200 OK`**: Hlášení bylo úspěšně přijato.
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"message": "Report received successfully."
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- **`400 Bad Request`**: Pokud chybí povinná pole nebo hodnota `location` je neplatná.
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"error": "Missing required fields."
|
||||||
|
}
|
||||||
|
```
|
||||||
|
</details>
|
||||||
235
web/content/posts/api-usage/v1.md
Normal file
235
web/content/posts/api-usage/v1.md
Normal file
@@ -0,0 +1,235 @@
|
|||||||
|
---
|
||||||
|
title: "API Dokumentace - Verze 1"
|
||||||
|
date: 2025-12-20
|
||||||
|
tags: ["api", "docs", "v1"]
|
||||||
|
hiddenInHomelist: true
|
||||||
|
---
|
||||||
|
|
||||||
|
Tato stránka detailně popisuje **Verzi 1 (v1)** API Ječná Rozvrh.
|
||||||
|
|
||||||
|
## Endpoint: `GET /versioned/v1`
|
||||||
|
|
||||||
|
Toto je hlavní endpoint, který poskytuje veškerá data o rozvrhu pro v1.
|
||||||
|
|
||||||
|
### Struktura Odpovědi
|
||||||
|
|
||||||
|
Odpověď je JSON objekt, který obsahuje tři hlavní klíče: `schedule`, `props`, a `status`.
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Zobrazit příklad struktury odpovědi</summary>
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"schedule": [ /* pole denních rozvrhů */ ],
|
||||||
|
"props": [ /* pole vlastností dnů */ ],
|
||||||
|
"status": { /* objekt stavu */ }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
</details>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Datové Struktury
|
||||||
|
|
||||||
|
#### Sekce: `schedule`
|
||||||
|
|
||||||
|
Tato sekce je pole, kde každý prvek představuje jeden den. Každý den je objekt, jehož klíče jsou názvy jednotlivých tříd (např. `A1`, `C2a`, `E4`) a speciální klíč `ABSENCE`.
|
||||||
|
|
||||||
|
##### Rozvrh Třídy
|
||||||
|
- **Klíč:** Název třídy (např. `"A1"`)
|
||||||
|
- **Hodnota:** Pole s 10 prvky, které reprezentují 10 vyučovacích hodin.
|
||||||
|
- `string`: Pokud je hodina normálně vyučována, obsahuje název předmětu nebo informaci o změně.
|
||||||
|
- `null`: Pokud hodina odpadá nebo pro ni není záznam.
|
||||||
|
- Text `(bude upřesněno)` může být připojen k předmětu, pokud je změna nejistá.
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Zobrazit příklad rozvrhu pro třídu A1</summary>
|
||||||
|
|
||||||
|
```json
|
||||||
|
"A1": [
|
||||||
|
"M 5 Kp(Ng)",
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
"(Me) (bude upřesněno)",
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
]
|
||||||
|
```
|
||||||
|
</details>
|
||||||
|
|
||||||
|
##### Absence Učitelů
|
||||||
|
- **Klíč:** `"ABSENCE"`
|
||||||
|
- **Hodnota:** Pole objektů, kde každý objekt specifikuje jednu absenci. Struktura objektu je následující:
|
||||||
|
- `teacher` (string | null): Celé jméno učitele, pokud je známé.
|
||||||
|
- `teacherCode` (string | null): Zkratka jména učitele (např. "me", "ad").
|
||||||
|
- `type` (string): Typ absence. Může nabývat následujících hodnot:
|
||||||
|
- `"wholeDay"`: Učitel chybí celý den.
|
||||||
|
- `"single"`: Učitel chybí jednu vyučovací hodinu.
|
||||||
|
- `"range"`: Učitel chybí v rozmezí několika hodin.
|
||||||
|
- `"exkurze"`: Učitel je na exkurzi.
|
||||||
|
- `"invalid"`: Záznam o absenci se nepodařilo zpracovat.
|
||||||
|
- `hours` (object | number | null): Specifikuje hodiny absence.
|
||||||
|
- `null`: Pro typy `wholeDay`, `exkurze`, a `invalid`.
|
||||||
|
- `number` (např. `3`): Pro typ `single`.
|
||||||
|
- `object` (např. `{ "from": 2, "to": 4 }`): Pro typ `range`.
|
||||||
|
- `original` (string | null): Pouze pro typ `invalid`, obsahuje původní nezpracovaný text.
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Zobrazit příklady absencí</summary>
|
||||||
|
|
||||||
|
**Celý den:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"teacher": "Jan Novák",
|
||||||
|
"teacherCode": "no",
|
||||||
|
"type": "wholeDay",
|
||||||
|
"hours": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Jedna hodina:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"teacher": "Jan Novák",
|
||||||
|
"teacherCode": "no",
|
||||||
|
"type": "single",
|
||||||
|
"hours": 1
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Rozsah hodin:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"teacher": "Jan Novák",
|
||||||
|
"teacherCode": "no",
|
||||||
|
"type": "range",
|
||||||
|
"hours": { "from": 2, "to": 4 }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Exkurze:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"teacher": "Jan Novák",
|
||||||
|
"teacherCode": "no",
|
||||||
|
"type": "exkurze",
|
||||||
|
"hours": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Neplatný záznam:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "invalid",
|
||||||
|
"teacher": null,
|
||||||
|
"teacherCode": null,
|
||||||
|
"hours": null,
|
||||||
|
"original": "Nezpracovatelný text"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
</details>
|
||||||
|
|
||||||
|
#### Sekce: `props` - Vlastnosti Dnů
|
||||||
|
|
||||||
|
Pole objektů, které doplňují metadata ke každému dni v poli `schedule`. Pořadí prvků v `props` přesně odpovídá pořadí dnů v `schedule`.
|
||||||
|
|
||||||
|
- `date` (string): Datum daného rozvrhu ve formátu `YYYY-MM-DD`.
|
||||||
|
- `priprava` (boolean): Hodnota je `true`, pokud je den součástí "přípravného týdne", jinak `false`.
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Zobrazit příklad props</summary>
|
||||||
|
|
||||||
|
```json
|
||||||
|
"props": [
|
||||||
|
{
|
||||||
|
"date": "2025-12-20",
|
||||||
|
"priprava": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"date": "2025-12-21",
|
||||||
|
"priprava": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
</details>
|
||||||
|
|
||||||
|
#### Sekce: `status` - Stav a Metadata
|
||||||
|
|
||||||
|
Objekt poskytující informace o aktuálnosti dat.
|
||||||
|
|
||||||
|
- `lastUpdated` (string): Čas poslední úspěšné aktualizace dat ve formátu `HH:MM`.
|
||||||
|
- `currentUpdateSchedule` (number): Interval v **minutách**, ve kterém scraper interně kontroluje a stahuje novou verzi rozvrhu. Tento interval se dynamicky mění v závislosti na denní době (kratší během vyučování, delší v noci).
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Zobrazit příklad status</summary>
|
||||||
|
|
||||||
|
```json
|
||||||
|
"status": {
|
||||||
|
"lastUpdated": "08:30",
|
||||||
|
"currentUpdateSchedule": 5
|
||||||
|
}
|
||||||
|
```
|
||||||
|
</details>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Kompletní Příklad Odpovědi z `GET /versioned/v1`
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Zobrazit kompletní příklad</summary>
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"schedule": [
|
||||||
|
{
|
||||||
|
"A1": [
|
||||||
|
"M 6 Kp(Ng)",
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
"(Me) (bude upřesněno)",
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
],
|
||||||
|
"C2": [
|
||||||
|
"M 6 Kp(Ng)",
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
"(Me) (bude upřesněno)",
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
],
|
||||||
|
"ABSENCE": [
|
||||||
|
{
|
||||||
|
"teacher": "Jan Novák",
|
||||||
|
"teacherCode": "no",
|
||||||
|
"type": "range",
|
||||||
|
"hours": {"from": 1, "to": 3}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"props": [
|
||||||
|
{
|
||||||
|
"date": "2025-12-20",
|
||||||
|
"priprava": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"status": {
|
||||||
|
"lastUpdated": "14:30",
|
||||||
|
"currentUpdateSchedule": 5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
</details>
|
||||||
14
web/content/posts/scraper-documentation/index.md
Normal file
14
web/content/posts/scraper-documentation/index.md
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
---
|
||||||
|
title: "Jak Funguje Scraper"
|
||||||
|
date: 2025-12-20
|
||||||
|
tags: ["scraper", "backend"]
|
||||||
|
---
|
||||||
|
|
||||||
|
Celý proces je automatizovaný a běží v pravidelných intervalech, které se mění v závislosti na denní době.
|
||||||
|
|
||||||
|
1. **Stažení Souboru:** Scraper se pomocí automatizovaného prohlížeče přihlásí na SharePoint SPŠE Ječná, kde je uložen oficiální Excel soubor s mimořádným rozvrhem. Po přihlášení tento soubor stáhne.
|
||||||
|
|
||||||
|
2. **Parsování Dat:** Po stažení skript otevře Excel soubor a začne z něj "číst" data. Prochází jednotlivé řádky a sloupce, aby identifikoval rozvrhy pro jednotlivé třídy a informace o absencích učitelů.
|
||||||
|
|
||||||
|
3. **Generování JSONu:** Všechna přečtená a zpracovaná data jsou následně uložena do jednoho souboru ve formátu JSON.
|
||||||
|
4. **Poskytnutí přes API:** Tento JSON soubor je finálním zdrojem dat, který API server používá.
|
||||||
5
web/content/search.md
Normal file
5
web/content/search.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
title: "Vyhledávání"
|
||||||
|
placeholder: Vyhledávejte v dokumentaci...
|
||||||
|
layout: "search"
|
||||||
|
---
|
||||||
72
web/hugo.yaml
Normal file
72
web/hugo.yaml
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
baseURL: https://jecnarozvrh.jzitnik.dev
|
||||||
|
title: Ječná Rozvrh API
|
||||||
|
theme: ["PaperMod"]
|
||||||
|
|
||||||
|
enableInlineShortcodes: true
|
||||||
|
enableRobotsTXT: true
|
||||||
|
buildDrafts: false
|
||||||
|
buildFuture: false
|
||||||
|
buildExpired: false
|
||||||
|
enableEmoji: true
|
||||||
|
pygmentsUseClasses: true
|
||||||
|
mainsections: ["posts", "papermod"]
|
||||||
|
|
||||||
|
minify:
|
||||||
|
disableXML: true
|
||||||
|
# minifyOutput: true
|
||||||
|
|
||||||
|
pagination:
|
||||||
|
disableAliases: false
|
||||||
|
pagerSize: 5
|
||||||
|
|
||||||
|
|
||||||
|
menu:
|
||||||
|
main:
|
||||||
|
- name: Vyhledávání
|
||||||
|
url: search/
|
||||||
|
weight: 10
|
||||||
|
- name: Autor
|
||||||
|
url: https://jzitnik.dev
|
||||||
|
|
||||||
|
outputs:
|
||||||
|
home:
|
||||||
|
- HTML
|
||||||
|
- RSS
|
||||||
|
- JSON
|
||||||
|
|
||||||
|
params:
|
||||||
|
env: production
|
||||||
|
author: Jakub Žitník
|
||||||
|
|
||||||
|
defaultTheme: auto
|
||||||
|
ShowShareButtons: false
|
||||||
|
ShowReadingTime: true
|
||||||
|
displayFullLangName: true
|
||||||
|
ShowPostNavLinks: true
|
||||||
|
ShowBreadCrumbs: true
|
||||||
|
ShowCodeCopyButtons: true
|
||||||
|
ShowRssButtonInSectionTermList: true
|
||||||
|
ShowAllPagesInArchive: true
|
||||||
|
ShowPageNums: true
|
||||||
|
ShowToc: true
|
||||||
|
|
||||||
|
homeInfoParams:
|
||||||
|
Title: "Ječná Rozvrh API"
|
||||||
|
Content: >
|
||||||
|
Oficiální webová stránka SPŠE Ječná Rozvrh API.
|
||||||
|
|
||||||
|
- Ječná Rozvrh API je API pro získávání mimořádného rozvrhu z SPŠE Ječná tabulky.
|
||||||
|
|
||||||
|
|
||||||
|
markup:
|
||||||
|
goldmark:
|
||||||
|
renderer:
|
||||||
|
unsafe: true
|
||||||
|
highlight:
|
||||||
|
noClasses: false
|
||||||
|
|
||||||
|
services:
|
||||||
|
instagram:
|
||||||
|
disableInlineCSS: true
|
||||||
|
x:
|
||||||
|
disableInlineCSS: true
|
||||||
1
web/layouts/partials/extend_head.html
Normal file
1
web/layouts/partials/extend_head.html
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<script type="module" src="https://cdn.jsdelivr.net/npm/@hotwired/turbo@latest/dist/turbo.es2017-esm.min.js"></script>
|
||||||
1
web/themes/PaperMod
Submodule
1
web/themes/PaperMod
Submodule
Submodule web/themes/PaperMod added at 7d061d56d4
Reference in New Issue
Block a user